summaryrefslogtreecommitdiff
path: root/src/rend2/tr_glsl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rend2/tr_glsl.c')
-rw-r--r--src/rend2/tr_glsl.c2825
1 files changed, 2825 insertions, 0 deletions
diff --git a/src/rend2/tr_glsl.c b/src/rend2/tr_glsl.c
new file mode 100644
index 00000000..823fce39
--- /dev/null
+++ b/src/rend2/tr_glsl.c
@@ -0,0 +1,2825 @@
+/*
+===========================================================================
+Copyright (C) 2006-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
+
+This file is part of XreaL source code.
+
+XreaL source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+XreaL source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with XreaL source code; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// tr_glsl.c
+#include "tr_local.h"
+
+void GLSL_BindNullProgram(void);
+
+// FIXME: Do something that isn't this messy
+static const char *fallbackGenericShader_vp =
+"attribute vec4 attr_Position;\r\nattribute vec4 attr_TexCoord0;\r\nattribut"
+"e vec4 attr_TexCoord1;\r\nattribute vec3 attr_Normal;\r\nattribute vec4 att"
+"r_Color;\r\n\r\n#if defined(USE_VERTEX_ANIMATION)\r\nattribute vec4 attr_Po"
+"sition2;\r\nattribute vec3 attr_Normal2;\r\n#endif\r\n\r\nuniform mat4 u_"
+"DiffuseTexMatrix;\r\nuniform vec3 u_ViewOrigin;\r\n\r\n#if defined(USE_TC"
+"GEN)\r\nuniform int u_TCGen0;\r\nuniform vec3 u_TCGen0Vector0;\r\nunif"
+"orm vec3 u_TCGen0Vector1;\r\n#endif\r\n\r\n#if defined(USE_FOG)\r\nunifor"
+"m vec4 u_FogDistance;\r\nuniform vec4 u_FogDepth;\r\nuniform float u_F"
+"ogEyeT;\r\nuniform vec4 u_FogColorMask;\r\n#endif\r\n\r\n#if defined(USE_"
+"DEFORM_VERTEXES)\r\nuniform int u_DeformGen;\r\nuniform float u_DeformP"
+"arams[5];\r\n#endif\r\n\r\nuniform float u_Time;\r\n\r\nuniform mat4 u_M"
+"odelViewProjectionMatrix;\r\nuniform vec4 u_BaseColor;\r\nuniform vec4 "
+"u_VertColor;\r\n\r\n#if defined(USE_RGBAGEN)\r\nuniform int u_ColorGen;"
+"\r\nuniform int u_AlphaGen;\r\nuniform vec3 u_AmbientLight;\r\nuniform"
+" vec3 u_DirectedLight;\r\nuniform vec4 u_LightOrigin;\r\nuniform float "
+" u_PortalRange;\r\n#endif\r\n\r\n#if defined(USE_VERTEX_ANIMATION)\r\nunifo"
+"rm float u_VertexLerp;\r\n#endif\r\n\r\nvarying vec2 var_DiffuseTex;\r\n"
+"#if defined(USE_LIGHTMAP)\r\nvarying vec2 var_LightTex;\r\n#endif\r\nvary"
+"ing vec4 var_Color;\r\n\r\nvec2 DoTexMatrix(vec2 st, vec3 position, mat4 "
+"texMatrix)\r\n{\r\n\tfloat amplitude = texMatrix[3][0];\r\n\tfloat phase = "
+"texMatrix[3][1];\r\n\tvec2 st2 = (texMatrix * vec4(st, 1.0, 0.0)).st;\r\n\r"
+"\n\tvec3 offsetPos = position.xyz / 1024.0;\r\n\toffsetPos.x += offsetPos.z"
+";\r\n\r\n\tvec2 texOffset = sin((offsetPos.xy + vec2(phase)) * 2.0 * M_PI);"
+"\r\n\t\r\n\treturn st2 + texOffset * amplitude;\r\n}\r\n\r\n#if defined(USE"
+"_DEFORM_VERTEXES)\r\nfloat triangle(float x)\r\n{\r\n\treturn max(1.0 - abs"
+"(x), 0);\r\n}\r\n\r\nfloat sawtooth(float x)\r\n{\r\n\treturn x - floor(x);"
+"\r\n}\r\n\r\nvec4 DeformPosition(const vec4 pos, const vec3 normal, const v"
+"ec2 st)\r\n{\r\n\tfloat base = u_DeformParams[0];\r\n\tfloat amplitude"
+" = u_DeformParams[1];\r\n\tfloat phase = u_DeformParams[2];\r\n\tfloat "
+"frequency = u_DeformParams[3];\r\n\tfloat spread = u_DeformParams[4];\r"
+"\n\t\r\n\tif (u_DeformGen == DGEN_BULGE)\r\n\t{\r\n\t\tphase *= M_PI * 0.25"
+" * st.x;\r\n\t}\r\n\telse // if (u_DeformGen <= DGEN_WAVE_INVERSE_SAWTOOTH)"
+"\r\n\t{\r\n\t\tphase += (pos.x + pos.y + pos.z) * spread;\r\n\t}\r\n\r\n\tf"
+"loat value = phase + (u_Time * frequency);\r\n\tfloat func;\r\n\r\n\tif (u_"
+"DeformGen == DGEN_WAVE_SIN)\r\n\t{\r\n\t\tfunc = sin(value * 2.0 * M_PI);\r"
+"\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE_SQUARE)\r\n\t{\r\n\t\tfunc = s"
+"ign(sin(value * 2.0 * M_PI));\r\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE"
+"_TRIANGLE)\r\n\t{\r\n\t\tfunc = triangle(value);\r\n\t}\r\n\telse if (u_Def"
+"ormGen == DGEN_WAVE_SAWTOOTH)\r\n\t{\r\n\t\tfunc = sawtooth(value);\r\n\t}"
+"\r\n\telse if (u_DeformGen == DGEN_WAVE_INVERSE_SAWTOOTH)\r\n\t{\r\n\t\tfun"
+"c = (1.0 - sawtooth(value));\r\n\t}\r\n\telse if (u_DeformGen == DGEN_BULGE"
+")\r\n\t{\r\n\t\tfunc = sin(value);\r\n\t}\r\n\t\r\n\tvec4 deformed = pos;\r"
+"\n\tdeformed.xyz += normal * (base + func * amplitude);\r\n\r\n\treturn def"
+"ormed;\r\n}\r\n#endif\r\n\r\n#if defined(USE_TCGEN)\r\nvec2 GenTexCoords(in"
+"t TCGen, vec4 position, vec3 normal, vec3 TCGenVector0, vec3 TCGenVector1)"
+"\r\n{\r\n\tvec2 tex = attr_TexCoord0.st;\r\n\r\n\tif (TCGen == TCGEN_LIGHTM"
+"AP)\r\n\t{\r\n\t\ttex = attr_TexCoord1.st;\r\n\t}\r\n\telse if (TCGen == TC"
+"GEN_ENVIRONMENT_MAPPED)\r\n\t{\r\n\t\tvec3 viewer = normalize(u_ViewOrigin "
+"- position.xyz);\r\n\t\tvec3 reflected = normal * 2.0 * dot(normal, viewer)"
+" - viewer;\r\n\r\n\t\ttex = reflected.yz * vec2(0.5, -0.5) + 0.5;\r\n\t}\r"
+"\n\telse if (TCGen == TCGEN_VECTOR)\r\n\t{\r\n\t\ttex = vec2(dot(position.x"
+"yz, TCGenVector0), dot(position.xyz, TCGenVector1));\r\n\t}\r\n\t\r\n\tretu"
+"rn tex;\r\n}\r\n#endif\r\n\r\nvoid main()\r\n{\r\n#if defined(USE_VERTEX_AN"
+"IMATION)\r\n\tvec4 position = mix(attr_Position, attr_Position2, u_VertexLe"
+"rp);\r\n\tvec3 normal = normalize(mix(attr_Normal, attr_Normal2, u_VertexLe"
+"rp));\r\n#else\r\n\tvec4 position = attr_Position;\r\n\tvec3 normal = attr_"
+"Normal;\r\n#endif\r\n\r\n#if defined(USE_DEFORM_VERTEXES)\r\n\tposition = D"
+"eformPosition(position, normal, attr_TexCoord0.st);\r\n#endif\r\n\r\n\tgl_P"
+"osition = u_ModelViewProjectionMatrix * position;\r\n\r\n#if defined(USE_TC"
+"GEN)\r\n\tvec2 tex = GenTexCoords(u_TCGen0, position, normal, u_TCGen0Vecto"
+"r0, u_TCGen0Vector1);\r\n#else\r\n\tvec2 tex = attr_TexCoord0.st;\r\n#endif"
+"\r\n\tvar_DiffuseTex = DoTexMatrix(tex, position.xyz, u_DiffuseTexMatrix);"
+"\r\n\r\n#if defined(USE_LIGHTMAP)\r\n\tvar_LightTex = attr_TexCoord1.st;\r"
+"\n#endif\r\n\r\n\tvar_Color = u_VertColor * attr_Color + u_BaseColor;\r\n\r"
+"\n#if defined(USE_RGBAGEN)\r\n\tif (u_ColorGen == CGEN_LIGHTING_DIFFUSE)\r"
+"\n\t{\r\n\t\tfloat incoming = max(dot(normal, u_LightOrigin.xyz), 0.0);\r\n"
+"\r\n\t\tvar_Color.rgb = min(u_DirectedLight * incoming + u_AmbientLight, 1."
+"0);\r\n\t}\r\n\t\r\n\tvec3 toView = u_ViewOrigin - position.xyz;\r\n\r\n\ti"
+"f (u_AlphaGen == AGEN_LIGHTING_SPECULAR)\r\n\t{\r\n\t\tvec3 lightDir = norm"
+"alize(vec3(-960.0, -1980.0, 96.0) - position.xyz);\r\n\t\tvec3 viewer = nor"
+"malize(toView);\r\n\t\tvec3 halfangle = normalize(lightDir + viewer);\r\n\t"
+"\t\r\n\t\tvar_Color.a = pow(max(dot(normal, halfangle), 0.0), 8.0);\r\n\t}"
+"\r\n\telse if (u_AlphaGen == AGEN_PORTAL)\r\n\t{\r\n\t\tfloat alpha = lengt"
+"h(toView) / u_PortalRange;\r\n\r\n\t\tvar_Color.a = min(alpha, 1.0);\r\n\t}"
+"\r\n\telse if (u_AlphaGen == AGEN_FRESNEL)\r\n\t{\r\n\t\tvec3 viewer = norm"
+"alize(toView);\r\n\t\t\r\n\t\tvar_Color.a = 0.10 + 0.90 * pow(1.0 - dot(nor"
+"mal, viewer), 5);\r\n\t}\r\n#endif\r\n\r\n#if defined (USE_FOG)\r\n\tfloat "
+"s = dot(position, u_FogDistance);\r\n\tfloat t = dot(position, u_FogDepth);"
+"\r\n\t\r\n\tif (t >= 1.0)\r\n\t{\r\n\t\ts *= t / (t - min(u_FogEyeT, 0.0));"
+"\r\n\t}\r\n\telse\r\n\t{\r\n\t\ts *= max(t + sign(u_FogEyeT), 0.0);\r\n\t}"
+"\r\n\t\r\n\ts = 1.0 - sqrt(clamp(s * 8.0, 0.0, 1.0));\r\n\t\r\n\tvar_Color "
+"*= u_FogColorMask * s + (vec4(1.0) - u_FogColorMask);\r\n#endif\r\n}\r\n";
+
+static const char *fallbackGenericShader_fp =
+"uniform sampler2D u_DiffuseMap;\r\n\r\n#if defined(USE_LIGHTMAP)\r\nuniform"
+" sampler2D u_LightMap;\r\n#endif\r\n\r\nuniform int u_Texture1Env;\r"
+"\n\r\nvarying vec2 var_DiffuseTex;\r\n\r\n#if defined(USE_LIGHTMAP)\r"
+"\nvarying vec2 var_LightTex;\r\n#endif\r\n\r\nvarying vec4 var_Co"
+"lor;\r\n\r\n\r\nvoid main()\r\n{\r\n\tvec4 color = texture2D(u_DiffuseMap,"
+" var_DiffuseTex);\r\n#if defined(USE_LIGHTMAP)\r\n\tvec4 color2 = texture2D"
+"(u_LightMap, var_LightTex);\r\n #if defined(RGBE_LIGHTMAP)\r\n\tcolor2.rgb"
+" *= exp2(color2.a * 255.0 - 128.0);\r\n\tcolor2.a = 1.0;\r\n #endif\r\n\r"
+"\n\tif (u_Texture1Env == TEXENV_MODULATE)\r\n\t{\r\n\t\tcolor *= color2;\r"
+"\n\t}\r\n\telse if (u_Texture1Env == TEXENV_ADD)\r\n\t{\r\n\t\tcolor += col"
+"or2;\r\n\t}\r\n\telse if (u_Texture1Env == TEXENV_REPLACE)\r\n\t{\r\n\t\tco"
+"lor = color2;\r\n\t}\r\n#endif\r\n\r\n\tgl_FragColor = color * var_Color;\r"
+"\n}\r\n";
+
+static const char *fallbackTextureColorShader_vp =
+"#version 120\r\n\r\nattribute vec4 attr_Position;\r\nattribute vec4 attr_Te"
+"xCoord0;\r\n\r\nuniform mat4 u_ModelViewProjectionMatrix;\r\n\r\nvarying "
+"vec2 var_Tex1;\r\n\r\n\r\nvoid main()\r\n{\r\n\tgl_Position = u_ModelView"
+"ProjectionMatrix * attr_Position;\r\n\tvar_Tex1 = attr_TexCoord0.st;\r\n}\r"
+"\n";
+
+static const char *fallbackTextureColorShader_fp =
+"#version 120\r\n\r\nuniform sampler2D u_DiffuseMap;\r\nuniform vec4 u_"
+"Color;\r\n\r\nvarying vec2 var_Tex1;\r\n\r\n\r\nvoid main()\r\n{\r"
+"\n\tgl_FragColor = texture2D(u_DiffuseMap, var_Tex1) * u_Color;\r\n}\r\n";
+
+static const char *fallbackFogPassShader_vp =
+"attribute vec4 attr_Position;\r\nattribute vec3 attr_Normal;\r\nattribute"
+" vec4 attr_TexCoord0;\r\n\r\n//#if defined(USE_VERTEX_ANIMATION)\r\nattrib"
+"ute vec4 attr_Position2;\r\nattribute vec3 attr_Normal2;\r\n//#endif\r\n"
+"\r\nuniform vec4 u_FogDistance;\r\nuniform vec4 u_FogDepth;\r\nunifor"
+"m float u_FogEyeT;\r\n\r\n//#if defined(USE_DEFORM_VERTEXES)\r\nuniform i"
+"nt u_DeformGen;\r\nuniform float u_DeformParams[5];\r\n//#endif\r\n\r"
+"\nuniform float u_Time;\r\nuniform mat4 u_ModelViewProjectionMatrix;\r"
+"\n\r\n//#if defined(USE_VERTEX_ANIMATION)\r\nuniform float u_VertexLerp;"
+"\r\n//#endif\r\n\r\nvarying float var_Scale;\r\n\r\n\r\nfloat triangle(fl"
+"oat x)\r\n{\r\n\treturn max(1.0 - abs(x), 0);\r\n}\r\n\r\nfloat sawtooth(fl"
+"oat x)\r\n{\r\n\treturn x - floor(x);\r\n}\r\n\r\nvec4 DeformPosition(const"
+" vec4 pos, const vec3 normal, const vec2 st)\r\n{\r\n\tif (u_DeformGen == 0"
+")\r\n\t{\r\n\t\treturn pos;\r\n\t}\r\n\r\n\tfloat base = u_DeformParam"
+"s[0];\r\n\tfloat amplitude = u_DeformParams[1];\r\n\tfloat phase = u_De"
+"formParams[2];\r\n\tfloat frequency = u_DeformParams[3];\r\n\tfloat spread "
+"= u_DeformParams[4];\r\n\t\t\r\n\tif (u_DeformGen <= DGEN_WAVE_INVERSE_S"
+"AWTOOTH)\r\n\t{\r\n\t\tphase += (pos.x + pos.y + pos.z) * spread;\r\n\t}\r"
+"\n\telse if (u_DeformGen == DGEN_BULGE)\r\n\t{\r\n\t\tphase *= M_PI * 0.25 "
+"* st.x;\r\n\t}\r\n\r\n\tfloat value = phase + (u_Time * frequency);\r\n\tfl"
+"oat func;\r\n\r\n\tif (u_DeformGen == DGEN_WAVE_SIN)\r\n\t{\r\n\t\tfunc = s"
+"in(value * 2.0 * M_PI);\r\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE_SQUAR"
+"E)\r\n\t{\r\n\t\tfunc = sign(sin(value * 2.0 * M_PI));\r\n\t}\r\n\telse if "
+"(u_DeformGen == DGEN_WAVE_TRIANGLE)\r\n\t{\r\n\t\tfunc = triangle(value);\r"
+"\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE_SAWTOOTH)\r\n\t{\r\n\t\tfunc ="
+" sawtooth(value);\r\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE_INVERSE_SAW"
+"TOOTH)\r\n\t{\r\n\t\tfunc = (1.0 - sawtooth(value));\r\n\t}\r\n\telse if (u"
+"_DeformGen == DGEN_BULGE)\r\n\t{\r\n\t\tfunc = sin(value);\r\n\t}\r\n\r\n\t"
+"vec4 deformed = pos;\r\n\tdeformed.xyz += normal * (base + func * amplitude"
+");\r\n\r\n\treturn deformed;\r\n\r\n}\r\n\r\nvoid main()\r\n{\r\n\tvec4 pos"
+"ition = mix(attr_Position, attr_Position2, u_VertexLerp);\r\n\tvec3 normal "
+"= normalize(mix(attr_Normal, attr_Normal2, u_VertexLerp));\r\n\r\n\tpositio"
+"n = DeformPosition(position, normal, attr_TexCoord0.st);\r\n\r\n\tgl_Positi"
+"on = u_ModelViewProjectionMatrix * position;\r\n\r\n\tfloat s = dot(positio"
+"n, u_FogDistance);\r\n\tfloat t = dot(position, u_FogDepth);\r\n\r\n\tif (t"
+" >= 1.0)\r\n\t{\r\n\t\ts *= t / (t - min(u_FogEyeT, 0.0));\r\n\t}\r\n\telse"
+"\r\n\t{\r\n\t\ts *= max(t + sign(u_FogEyeT), 0.0);\r\n\t}\r\n\r\n\tvar_Scal"
+"e = s * 8.0;\r\n}\r\n";
+
+static const char *fallbackFogPassShader_fp =
+"uniform vec4 u_Color;\r\n\r\nvarying float var_Scale;\r\n\r\nvoid main()\r"
+"\n{\r\n\tgl_FragColor = u_Color;\r\n\tgl_FragColor.a *= sqrt(clamp(var_Scal"
+"e, 0.0, 1.0));\r\n}\r\n";
+
+static const char *fallbackDlightShader_vp =
+"attribute vec4 attr_Position;\r\nattribute vec4 attr_TexCoord0;\r\nattribut"
+"e vec3 attr_Normal;\r\n\r\nuniform vec4 u_DlightInfo;\r\n\r\nuniform int "
+" u_DeformGen;\r\nuniform float u_DeformParams[5];\r\n\r\nuniform float "
+"u_Time;\r\nuniform vec4 u_Color;\r\nuniform mat4 u_ModelViewProjectionM"
+"atrix;\r\n\r\nvarying vec2 var_Tex1;\r\nvarying vec4 var_Color;\r\n\r\n"
+"float triangle(float x)\r\n{\r\n\treturn max(1.0 - abs(x), 0);\r\n}\r\n\r\n"
+"float sawtooth(float x)\r\n{\r\n\treturn x - floor(x);\r\n}\r\n\r\nvec4 Def"
+"ormPosition(const vec4 pos, const vec3 normal, const vec2 st)\r\n{\r\n\tif "
+"(u_DeformGen == 0)\r\n\t{\r\n\t\treturn pos;\r\n\t}\r\n\r\n\tfloat base = "
+" u_DeformParams[0];\r\n\tfloat amplitude = u_DeformParams[1];\r\n\tfloat"
+" phase = u_DeformParams[2];\r\n\tfloat frequency = u_DeformParams[3];\r"
+"\n\tfloat spread = u_DeformParams[4];\r\n\t\t\r\n\tif (u_DeformGen <= DG"
+"EN_WAVE_INVERSE_SAWTOOTH)\r\n\t{\r\n\t\tphase += (pos.x + pos.y + pos.z) * "
+"spread;\r\n\t}\r\n\telse if (u_DeformGen == DGEN_BULGE)\r\n\t{\r\n\t\tphase"
+" *= M_PI * 0.25 * st.x;\r\n\t}\r\n\r\n\tfloat value = phase + (u_Time * fre"
+"quency);\r\n\tfloat func;\r\n\r\n\tif (u_DeformGen == DGEN_WAVE_SIN)\r\n\t{"
+"\r\n\t\tfunc = sin(value * 2.0 * M_PI);\r\n\t}\r\n\telse if (u_DeformGen =="
+" DGEN_WAVE_SQUARE)\r\n\t{\r\n\t\tfunc = sign(sin(value * 2.0 * M_PI));\r\n"
+"\t}\r\n\telse if (u_DeformGen == DGEN_WAVE_TRIANGLE)\r\n\t{\r\n\t\tfunc = t"
+"riangle(value);\r\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE_SAWTOOTH)\r\n"
+"\t{\r\n\t\tfunc = sawtooth(value);\r\n\t}\r\n\telse if (u_DeformGen == DGEN"
+"_WAVE_INVERSE_SAWTOOTH)\r\n\t{\r\n\t\tfunc = (1.0 - sawtooth(value));\r\n\t"
+"}\r\n\telse if (u_DeformGen == DGEN_BULGE)\r\n\t{\r\n\t\tfunc = sin(value);"
+"\r\n\t}\r\n\r\n\tvec4 deformed = pos;\r\n\tdeformed.xyz += normal * (base +"
+" func * amplitude);\r\n\r\n\treturn deformed;\r\n\r\n}\r\n\r\nvoid main()\r"
+"\n{\r\n\tvec4 position = attr_Position;\r\n\tvec3 normal = attr_Normal;\r\n"
+"\r\n\tposition = DeformPosition(position, normal, attr_TexCoord0.st);\r\n\r"
+"\n\tgl_Position = u_ModelViewProjectionMatrix * position;\r\n\t\t\r\n\tvec3"
+" dist = u_DlightInfo.xyz - position.xyz;\t\r\n\r\n\tfloat diffz = abs(dist."
+"z);\r\n\tfloat radius = 1.0 / u_DlightInfo.a;\r\n\r\n\tvec2 tex = vec2(0.5)"
+" + dist.xy * u_DlightInfo.a;\r\n\tfloat dlightmod = max(sign(dot(dist, norm"
+"al)), 0.0);\r\n\tdlightmod *= clamp(2.0 * (radius - diffz) * u_DlightInfo.a"
+", 0.0, 1.0);\r\n\r\n\tvar_Tex1 = tex;\r\n\tvar_Color = u_Color;\r\n\tvar_Co"
+"lor.rgb *= dlightmod;\r\n}\r\n";
+
+static const char *fallbackDlightShader_fp =
+"uniform sampler2D u_DiffuseMap;\r\n\r\nvarying vec2 var_Tex1;\r\nvaryi"
+"ng vec4 var_Color;\r\n\r\n\r\nvoid main()\r\n{\r\n\tvec4 color = textu"
+"re2D(u_DiffuseMap, var_Tex1);\r\n\r\n\tgl_FragColor = color * var_Color;\r"
+"\n}\r\n";
+
+static const char *fallbackLightallShader_vp =
+"attribute vec4 attr_TexCoord0;\r\n#if defined(USE_LIGHTMAP)\r\nattribute ve"
+"c4 attr_TexCoord1;\r\n#endif\r\nattribute vec4 attr_Color;\r\n\r\nattribute"
+" vec4 attr_Position;\r\nattribute vec3 attr_Normal;\r\n\r\n#if defined(USE_"
+"VERT_TANGENT_SPACE)\r\nattribute vec3 attr_Tangent;\r\nattribute vec3 attr_"
+"Bitangent;\r\n#endif\r\n\r\n#if defined(USE_VERTEX_ANIMATION)\r\nattribute "
+"vec4 attr_Position2;\r\nattribute vec3 attr_Normal2;\r\n #if defined(USE_V"
+"ERT_TANGENT_SPACE)\r\nattribute vec3 attr_Tangent2;\r\nattribute vec3 attr_"
+"Bitangent2;\r\n #endif\r\n#endif\r\n\r\n#if defined(USE_LIGHT) && !defined"
+"(USE_LIGHT_VECTOR)\r\nattribute vec3 attr_LightDirection;\r\n#endif\r\n\r\n"
+"#if defined(TCGEN_ENVIRONMENT) || defined(USE_NORMALMAP) || defined(USE_LIG"
+"HT) && !defined(USE_FAST_LIGHT)\r\nuniform vec3 u_ViewOrigin;\r\n#endif\r"
+"\n\r\nuniform mat4 u_DiffuseTexMatrix;\r\nuniform mat4 u_ModelViewProje"
+"ctionMatrix;\r\nuniform vec4 u_BaseColor;\r\nuniform vec4 u_VertColor;"
+"\r\n\r\n#if defined(USE_MODELMATRIX)\r\nuniform mat4 u_ModelMatrix;\r\n#e"
+"ndif\r\n\r\n#if defined(USE_VERTEX_ANIMATION)\r\nuniform float u_VertexLer"
+"p;\r\n#endif\r\n\r\n#if defined(USE_LIGHT_VECTOR)\r\nuniform vec4 u_Light"
+"Origin;\r\n #if defined(USE_FAST_LIGHT)\r\nuniform vec3 u_DirectedLight;"
+"\r\nuniform vec3 u_AmbientLight;\r\nuniform float u_LightRadius;\r\n #e"
+"ndif\r\n#endif\r\n\r\nvarying vec2 var_DiffuseTex;\r\n\r\n#if defined(USE"
+"_LIGHTMAP)\r\nvarying vec2 var_LightTex;\r\n#endif\r\n\r\n#if defined(USE"
+"_NORMALMAP) || defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)\r\nvarying ve"
+"c3 var_SampleToView;\r\n#endif\r\n\r\nvarying vec4 var_Color;\r\nvaryin"
+"g vec3 var_Position;\r\nvarying vec3 var_Normal;\r\n\r\n#if defined(USE"
+"_VERT_TANGENT_SPACE)\r\nvarying vec3 var_Tangent;\r\nvarying vec3 var_B"
+"itangent;\r\n#endif\r\n\r\nvarying vec3 var_VertLight;\r\n\r\n#if defined"
+"(USE_LIGHT) && !defined(USE_DELUXEMAP)\r\nvarying vec3 var_WorldLight;\r"
+"\n#endif\r\n\r\nvarying vec4 var_ScreenPos;\r\n\r\nvec2 DoTexMatrix(vec2 "
+"st, vec3 position, mat4 texMatrix)\r\n{\r\n\tvec2 st2 = (texMatrix * vec4(s"
+"t, 1, 0)).st;\r\n\r\n\tvec3 offsetPos = position.xyz / 1024.0;\r\n\toffsetP"
+"os.x += offsetPos.z;\r\n\r\n\tvec2 texOffset = sin((offsetPos.xy + vec2(tex"
+"Matrix[3][1])) * 2.0 * M_PI);\r\n\t\r\n\treturn st2 + texOffset * texMatrix"
+"[3][0];\r\n}\r\n\r\nvoid main()\r\n{\r\n#if defined(USE_VERTEX_ANIMATION)\r"
+"\n\tvec4 position = mix(attr_Position, attr_Position2, u_VertexLerp);\r\n"
+"\tvec3 normal = normalize(mix(attr_Normal, attr_Normal2, u_VertexL"
+"erp));\r\n #if defined(USE_VERT_TANGENT_SPACE)\r\n\tvec3 tangent = norma"
+"lize(mix(attr_Tangent, attr_Tangent2, u_VertexLerp));\r\n\tvec3 bitange"
+"nt = normalize(mix(attr_Bitangent, attr_Bitangent2, u_VertexLerp));\r\n #e"
+"ndif\r\n#else\r\n\tvec4 position = attr_Position;\r\n\tvec3 normal = at"
+"tr_Normal;\r\n #if defined(USE_VERT_TANGENT_SPACE)\r\n\tvec3 tangent = a"
+"ttr_Tangent;\r\n\tvec3 bitangent = attr_Bitangent;\r\n #endif\r\n#endif\r"
+"\n\r\n\tgl_Position = u_ModelViewProjectionMatrix * position;\r\n\tvar_Scre"
+"enPos = gl_Position;\r\n\r\n#if (defined(USE_LIGHTMAP) || defined(USE_LIGHT"
+"_VERTEX)) && !defined(USE_DELUXEMAP)\r\n\tvec3 worldLight = attr_LightDirec"
+"tion;\r\n#endif\r\n\t\r\n#if defined(USE_MODELMATRIX)\r\n\tposition = u_Mo"
+"delMatrix * position;\r\n\tnormal = (u_ModelMatrix * vec4(normal, 0.0))."
+"xyz;\r\n #if defined(USE_VERT_TANGENT_SPACE)\r\n\ttangent = (u_ModelMatr"
+"ix * vec4(tangent, 0.0)).xyz;\r\n\tbitangent = (u_ModelMatrix * vec4(bitang"
+"ent, 0.0)).xyz;\r\n #endif\r\n\r\n #if defined(USE_LIGHTMAP) && !defined("
+"USE_DELUXEMAP)\r\n\tworldLight = (u_ModelMatrix * vec4(worldLight, 0.0)).xy"
+"z;\r\n #endif\r\n#endif\r\n\r\n\tvar_Position = position.xyz;\r\n\r\n#if d"
+"efined(TCGEN_ENVIRONMENT) || defined(USE_NORMALMAP) || defined(USE_LIGHT) &"
+"& !defined(USE_FAST_LIGHT)\r\n\tvec3 SampleToView = u_ViewOrigin - position"
+".xyz;\r\n#endif\r\n\r\n#if defined(USE_NORMALMAP) || defined(USE_LIGHT) && "
+"!defined(USE_FAST_LIGHT)\r\n\tvar_SampleToView = SampleToView;\r\n#endif\r"
+"\n\r\n#if defined(TCGEN_ENVIRONMENT)\r\n\tvec3 viewer = normalize(SampleToV"
+"iew);\r\n\tvec3 reflected = normal * 2.0 * dot(normal, viewer) - viewer;\r"
+"\n\r\n\tvec2 tex = reflected.yz * vec2(0.5, -0.5) + 0.5;\r\n#else\r\n\tvec2"
+" tex = attr_TexCoord0.st;\r\n#endif\r\n\r\n\tvar_DiffuseTex = DoTexMatrix(t"
+"ex, position.xyz, u_DiffuseTexMatrix);\r\n\r\n#if defined(USE_LIGHTMAP)\r\n"
+"\tvar_LightTex = attr_TexCoord1.st;\r\n#endif\r\n \r\n\tvar_Normal = norma"
+"l;\r\n#if defined(USE_VERT_TANGENT_SPACE)\r\n\tvar_Tangent = tangent;\r\n\t"
+"var_Bitangent = bitangent;\r\n#endif\r\n\r\n#if defined(USE_LIGHT) && !defi"
+"ned(USE_DELUXEMAP)\r\n #if defined(USE_LIGHT_VECTOR)\r\n\tvec3 worldLight "
+"= u_LightOrigin.xyz - (position.xyz * u_LightOrigin.w);\r\n #endif\r\n\r\n"
+"\tworldLight += normal * 0.0001;\r\n\tvar_WorldLight = worldLight;\r\n#endi"
+"f\r\n\t\r\n#if defined(USE_LIGHT_VERTEX)\r\n var_VertLight = attr_Color."
+"rgb;\r\n #if !defined(USE_FAST_LIGHT)\r\n\tvar_VertLight /= max(dot(normal"
+", normalize(worldLight)), 0.004);\r\n #endif\r\n\tvar_Color.rgb = u_BaseCo"
+"lor.rgb;\r\n\tvar_Color.a = u_VertColor.a * attr_Color.a + u_BaseColor.a;\r"
+"\n#else\r\n\tvar_Color = u_VertColor * attr_Color + u_BaseColor;\r\n#endif"
+"\r\n\r\n#if defined(USE_LIGHT_VECTOR) && defined(USE_FAST_LIGHT)\r\n #if d"
+"efined(USE_INVSQRLIGHT)\r\n\tfloat intensity = 1.0 / dot(worldLight, worldL"
+"ight);\r\n #else\r\n\tfloat intensity = clamp((1.0 - dot(worldLight, world"
+"Light) / (u_LightRadius * u_LightRadius)) * 1.07, 0.0, 1.0);\r\n #endif\r"
+"\n\tfloat NL = clamp(dot(normal, normalize(worldLight)), 0.0, 1.0);\r\n\r\n"
+"\tvar_VertLight = u_DirectedLight * intensity * NL + u_AmbientLight;\r\n#en"
+"dif\r\n}\r\n";
+
+static const char *fallbackLightallShader_fp =
+"uniform sampler2D u_DiffuseMap;\r\n\r\n#if defined(USE_LIGHTMAP)\r\nuniform"
+" sampler2D u_LightMap;\r\n#endif\r\n\r\n#if defined(USE_NORMALMAP)\r\nunifo"
+"rm sampler2D u_NormalMap;\r\n#endif\r\n\r\n#if defined(USE_DELUXEMAP)\r\nun"
+"iform sampler2D u_DeluxeMap;\r\n#endif\r\n\r\n#if defined(USE_SPECULARMAP)"
+"\r\nuniform sampler2D u_SpecularMap;\r\n#endif\r\n\r\n#if defined(USE_SHADO"
+"WMAP)\r\nuniform sampler2D u_ShadowMap;\r\n#endif\r\n\r\nuniform vec3 "
+"u_ViewOrigin;\r\n\r\n#if defined(USE_LIGHT_VECTOR)\r\nuniform vec3 u_D"
+"irectedLight;\r\nuniform vec3 u_AmbientLight;\r\nuniform float u_L"
+"ightRadius;\r\n#endif\r\n\r\n#if defined(USE_LIGHT)\r\nuniform vec2 u_"
+"MaterialInfo;\r\n#endif\r\n\r\nvarying vec2 var_DiffuseTex;\r\n#if def"
+"ined(USE_LIGHTMAP)\r\nvarying vec2 var_LightTex;\r\n#endif\r\nvarying "
+"vec4 var_Color;\r\nvarying vec3 var_Position;\r\n\r\nvarying vec3"
+" var_SampleToView;\r\n\r\nvarying vec3 var_Normal;\r\n#if defined"
+"(USE_VERT_TANGENT_SPACE)\r\nvarying vec3 var_Tangent;\r\nvarying vec3 "
+" var_Bitangent;\r\n#endif\r\n\r\nvarying vec3 var_VertLight;\r\n\r"
+"\n#if defined(USE_LIGHT) && !defined(USE_DELUXEMAP)\r\nvarying vec3 va"
+"r_WorldLight;\r\n#endif\r\n\r\nvarying vec4 var_ScreenPos;\r\n\r\n#define"
+" EPSILON 0.00000001\r\n\r\n#if defined(USE_PARALLAXMAP)\r\nfloat SampleHeig"
+"ht(sampler2D normalMap, vec2 t)\r\n{\r\n #if defined(SWIZZLE_NORMALMAP)\r"
+"\n\treturn texture2D(normalMap, t).r;\r\n #else\r\n\treturn texture2D(norm"
+"alMap, t).a;\r\n #endif\r\n}\r\n\r\nfloat RayIntersectDisplaceMap(vec2 dp,"
+" vec2 ds, sampler2D normalMap)\r\n{\r\n\tconst int linearSearchSteps = 16;"
+"\r\n\tconst int binarySearchSteps = 6;\r\n\r\n\tfloat depthStep = 1.0 / flo"
+"at(linearSearchSteps);\r\n\r\n\t// current size of search window\r\n\tfloat"
+" size = depthStep;\r\n\r\n\t// current depth position\r\n\tfloat depth = 0."
+"0;\r\n\r\n\t// best match found (starts with last position 1.0)\r\n\tfloat "
+"bestDepth = 1.0;\r\n\r\n\t// search front to back for first point inside ob"
+"ject\r\n\tfor(int i = 0; i < linearSearchSteps - 1; ++i)\r\n\t{\r\n\t\tdept"
+"h += size;\r\n\t\t\r\n\t\tfloat t = 1.0 - SampleHeight(normalMap, dp + ds *"
+" depth);\r\n\t\t\r\n\t\tif(bestDepth > 0.996)\t\t// if no depth found yet\r"
+"\n\t\t\tif(depth >= t)\r\n\t\t\t\tbestDepth = depth;\t// store best depth\r"
+"\n\t}\r\n\r\n\tdepth = bestDepth;\r\n\t\r\n\t// recurse around first point "
+"(depth) for closest match\r\n\tfor(int i = 0; i < binarySearchSteps; ++i)\r"
+"\n\t{\r\n\t\tsize *= 0.5;\r\n\r\n\t\tfloat t = 1.0 - SampleHeight(normalMap"
+", dp + ds * depth);\r\n\t\t\r\n\t\tif(depth >= t)\r\n\t\t{\r\n\t\t\tbestDep"
+"th = depth;\r\n\t\t\tdepth -= 2.0 * size;\r\n\t\t}\r\n\r\n\t\tdepth += size"
+";\r\n\t}\r\n\r\n\treturn bestDepth;\r\n}\r\n#endif\r\n\r\nfloat CalcDiffuse"
+"(vec3 N, vec3 L, vec3 E, float NE, float NL, float fzero, float shininess)"
+"\r\n{\r\n #if defined(USE_OREN_NAYAR) || defined(USE_TRIACE_OREN_NAYAR)\r"
+"\n\tfloat gamma = dot(E, L) - NE * NL;\r\n\tfloat B = 2.22222 + 0.1 * shini"
+"ness;\r\n\t\t\r\n\t#if defined(USE_OREN_NAYAR)\r\n\tfloat A = 1.0 - 1.0 / ("
+"2.0 + 0.33 * shininess);\r\n\tgamma = clamp(gamma, 0.0, 1.0);\r\n\t#endif\r"
+"\n\t\r\n\t#if defined(USE_TRIACE_OREN_NAYAR)\r\n\tfloat A = 1.0 - 1.0 / (2."
+"0 + 0.65 * shininess);\r\n\r\n\tif (gamma >= 0.0)\r\n\t#endif\r\n\t{\r\n\t"
+"\tB *= max(max(NL, NE), EPSILON);\r\n\t}\r\n\r\n\treturn A + gamma / B;\r\n"
+" #else\r\n\treturn 1.0 - fzero;\r\n #endif\r\n}\r\n\r\n#if defined(USE_SP"
+"ECULARMAP)\r\nfloat CalcSpecular(float NH, float NL, float NE, float EH, fl"
+"oat fzero, float shininess)\r\n{\r\n #if defined(USE_BLINN) || defined(USE"
+"_TRIACE) || defined(USE_TORRANCE_SPARROW)\r\n\tfloat blinn = pow(NH, shinin"
+"ess);\r\n #endif\r\n\r\n #if defined(USE_BLINN)\r\n\treturn blinn;\r\n #"
+"endif\r\n\r\n #if defined(USE_COOK_TORRANCE) || defined (USE_TRIACE) || de"
+"fined (USE_TORRANCE_SPARROW)\r\n\tfloat fresnel = fzero + (1.0 - fzero) * p"
+"ow(1.0 - EH, 5);\r\n #endif\r\n\r\n #if defined(USE_COOK_TORRANCE) || def"
+"ined(USE_TORRANCE_SPARROW)\r\n\tfloat geo = 2.0 * NH * min(NE, NL);\r\n\tge"
+"o /= max(EH, geo);\r\n #endif \r\n\r\n #if defined(USE_COOK_TORRANCE)\r"
+"\n\tfloat m = sqrt(2.0 / max(shininess, EPSILON));\r\n\r\n\tfloat m_sq = m "
+"* m;\r\n\tfloat NH_sq = NH * NH;\r\n\tfloat beckmann = exp((NH_sq - 1.0) / "
+"max(m_sq * NH_sq, EPSILON)) / max(4.0 * m_sq * NH_sq * NH_sq, EPSILON);\r\n"
+"\r\n\treturn fresnel * geo * beckmann / max(NE, EPSILON);\r\n #endif\r\n\r"
+"\n #if defined(USE_TRIACE)\r\n\tfloat scale = 0.1248582 * shininess + 0.26"
+"91817;\r\n\r\n\treturn fresnel * scale * blinn / max(max(NL, NE), EPSILON);"
+"\r\n #endif\r\n \r\n #if defined(USE_TORRANCE_SPARROW)\r\n\tfloat scale "
+"= 0.125 * shininess + 1.0;\r\n\r\n\treturn fresnel * geo * scale * blinn / "
+"max(NE, EPSILON);\r\n #endif\r\n}\r\n#endif\r\n\r\nvoid main()\r\n{\r\n#if"
+" defined(USE_LIGHT) || defined(USE_NORMALMAP)\r\n\tvec3 surfNormal = normal"
+"ize(var_Normal);\r\n#endif\r\n\r\n#if defined(USE_DELUXEMAP)\r\n\tvec3 worl"
+"dLight = 2.0 * texture2D(u_DeluxeMap, var_LightTex).xyz - vec3(1.0);\r\n\t/"
+"/worldLight += var_WorldLight * 0.0001;\r\n#elif defined(USE_LIGHT)\r\n\tve"
+"c3 worldLight = var_WorldLight;\r\n#endif\r\n\r\n#if defined(USE_LIGHTMAP)"
+"\r\n\tvec4 lightSample = texture2D(u_LightMap, var_LightTex).rgba;\r\n #if"
+" defined(RGBE_LIGHTMAP)\r\n\tlightSample.rgb *= exp2(lightSample.a * 255.0 "
+"- 128.0);\r\n #endif\r\n\tvec3 directedLight = lightSample.rgb;\r\n#elif d"
+"efined(USE_LIGHT_VECTOR)\r\n #if defined(USE_FAST_LIGHT)\r\n\tvec3 directe"
+"dLight = var_VertLight;\r\n #else\r\n #if defined(USE_INVSQRLIGHT)\r\n"
+"\tfloat intensity = 1.0 / dot(worldLight, worldLight);\r\n #else\r\n\tfl"
+"oat intensity = clamp((1.0 - dot(worldLight, worldLight) / (u_LightRadius *"
+" u_LightRadius)) * 1.07, 0.0, 1.0);\r\n #endif\r\n\r\n\tvec3 directedLig"
+"ht = u_DirectedLight * intensity;\r\n\tvec3 ambientLight = u_AmbientLight;"
+"\r\n #endif\r\n\r\n #if defined(USE_SHADOWMAP)\r\n\tvec2 shadowTex = var_"
+"ScreenPos.xy / var_ScreenPos.w * 0.5 + 0.5;\r\n\tdirectedLight *= texture2D"
+"(u_ShadowMap, shadowTex).r;\r\n #endif\r\n#elif defined(USE_LIGHT_VERTEX)"
+"\r\n\tvec3 directedLight = var_VertLight;\r\n#endif\r\n\t\r\n#if defined(TC"
+"GEN_ENVIRONMENT) || defined(USE_NORMALMAP) || (defined(USE_LIGHT) && !defin"
+"ed(USE_FAST_LIGHT))\r\n\tvec3 SampleToView = normalize(var_SampleToView);\r"
+"\n#endif\r\n\tvec2 tex = var_DiffuseTex;\r\n\r\n\tfloat ambientDiff = 1.0;"
+"\r\n\r\n#if defined(USE_NORMALMAP)\r\n #if defined(USE_VERT_TANGENT_SPACE)"
+"\r\n vec3 tangent = var_Tangent;\r\n\tvec3 bitangent = var_Bitangent;"
+"\r\n #else\r\n\tvec3 q0 = dFdx(var_Position);\r\n\tvec3 q1 = dFdy(var_Po"
+"sition);\r\n\tvec2 st0 = dFdx(tex);\r\n\tvec2 st1 = dFdy(tex);\r\n\tfloat d"
+"ir = sign(st1.t * st0.s - st0.t * st1.s);\r\n\r\n\tvec3 tangent = normali"
+"ze( q0 * st1.t - q1 * st0.t) * dir;\r\n\tvec3 bitangent = -normalize( q0 * "
+"st1.s - q1 * st0.s) * dir;\r\n #endif\r\n\r\n\tmat3 tangentToWorld = mat3("
+"tangent, bitangent, var_Normal);\r\n\r\n #if defined(USE_PARALLAXMAP)\r\n"
+"\tvec3 offsetDir = normalize(SampleToView * tangentToWorld);\r\n #if 0\r"
+"\n float height = SampleHeight(u_NormalMap, tex);\r\n\tfloat pdist = 0.0"
+"5 * height - (0.05 / 2.0);\r\n #else\r\n\toffsetDir.xy *= -0.05 / offset"
+"Dir.z;\r\n\tfloat pdist = RayIntersectDisplaceMap(tex, offsetDir.xy, u_Norm"
+"alMap);\r\n #endif\t\r\n\ttex += offsetDir.xy * pdist;\r\n #endif\r\n "
+"#if defined(SWIZZLE_NORMALMAP)\r\n\tvec3 normal = 2.0 * texture2D(u_NormalM"
+"ap, tex).agb - 1.0;\r\n #else\r\n\tvec3 normal = 2.0 * texture2D(u_NormalM"
+"ap, tex).rgb - 1.0;\r\n #endif\r\n\tnormal.z = sqrt(clamp(1.0 - dot(normal"
+".xy, normal.xy), 0.0, 1.0));\r\n\tvec3 worldNormal = tangentToWorld * norma"
+"l;\r\n #if defined(r_normalAmbient)\r\n\tambientDiff = 0.781341 * normal.z"
+" + 0.218659;\r\n #endif\r\n#elif defined(USE_LIGHT)\r\n\tvec3 worldNormal "
+"= surfNormal;\r\n#endif\r\n\r\n#if (defined(USE_LIGHT) && !defined(USE_FAST"
+"_LIGHT)) || (defined(TCGEN_ENVIRONMENT) && defined(USE_NORMALMAP))\r\n\twor"
+"ldNormal = normalize(worldNormal);\r\n#endif\r\n\r\n#if defined(TCGEN_ENVIR"
+"ONMENT) && defined(USE_NORMALMAP)\r\n\tvec3 reflected = worldNormal * 2.0 *"
+" dot(worldNormal, SampleToView) - SampleToView;\r\n\r\n\ttex = reflected.yz"
+" * vec2(0.5, -0.5) + 0.5;\r\n#endif\r\n\r\n\tvec4 diffuse = texture2D(u_Dif"
+"fuseMap, tex);\r\n\r\n#if defined(USE_LIGHT) && defined(USE_FAST_LIGHT)\r\n"
+"\tdiffuse.rgb *= directedLight;\r\n#elif defined(USE_LIGHT)\r\n\tworldLight"
+" = normalize(worldLight);\r\n\r\n #if defined(USE_LIGHTMAP)\r\n\tdirectedL"
+"ight /= max(dot(surfNormal, worldLight), 0.004);\r\n #endif\r\n\r\n #if d"
+"efined(USE_LIGHTMAP) || defined(USE_LIGHT_VERTEX)\r\n\t#if defined(r_normal"
+"Ambient)\r\n\tvec3 ambientLight = directedLight * r_normalAmbient;\r\n\tdir"
+"ectedLight -= ambientLight;\r\n #else\r\n\tvec3 ambientLight = vec3(0);"
+"\r\n #endif\r\n #endif\r\n\r\n\tfloat NL = clamp(dot(worldNormal, worl"
+"dLight), 0.0, 1.0);\r\n\tfloat surfNL = clamp(dot(surfNormal, worldLight"
+"), 0.0, 1.0);\r\n\tNL = min(NL, surfNL * 2.0);\r\n\tfloat NE = clamp(dot("
+"worldNormal, SampleToView), 0.0, 1.0);\r\n\t\r\n\tfloat fzero = u_Material"
+"Info.x;\r\n\tfloat shininess = u_MaterialInfo.y;\r\n #if defined(USE_SPECU"
+"LARMAP)\r\n\tvec4 specular = texture2D(u_SpecularMap, tex);\r\n\t//specular"
+".rgb = clamp(specular.rgb - diffuse.rgb, 0.0, 1.0);\r\n\tshininess *= specu"
+"lar.a;\r\n #endif\r\n\tfloat directedDiff = NL * CalcDiffuse(worldNormal, "
+"worldLight, SampleToView, NE, NL, fzero, shininess);\r\n\tdiffuse.rgb *= di"
+"rectedLight * directedDiff + ambientDiff * ambientLight;\r\n \r\n #if def"
+"ined(USE_SPECULARMAP)\r\n\tvec3 halfAngle = normalize(worldLight + SampleTo"
+"View);\r\n\r\n\tfloat EH = clamp(dot(SampleToView, halfAngle), 0.0, 1.0);\r"
+"\n\tfloat NH = clamp(dot(worldNormal, halfAngle), 0.0, 1.0);\r\n\r\n\tfloa"
+"t directedSpec = NL * CalcSpecular(NH, NL, NE, EH, fzero, shininess);\r\n "
+"\r\n #if defined(r_normalAmbient)\r\n\tvec3 ambientHalf = normalize(surf"
+"Normal + SampleToView);\r\n\tfloat ambientSpec = max(dot(ambientHalf, world"
+"Normal) + 0.5, 0.0);\r\n\tambientSpec *= ambientSpec * 0.44;\r\n\tambientSp"
+"ec = pow(ambientSpec, shininess) * fzero;\r\n\tspecular.rgb *= directedSpec"
+" * directedLight + ambientSpec * ambientLight;\r\n #else\r\n\tspecular.r"
+"gb *= directedSpec * directedLight;\r\n #endif\r\n #endif\r\n#endif\r\n"
+"\r\n\tgl_FragColor = diffuse;\r\n\r\n#if defined(USE_SPECULARMAP) && define"
+"d(USE_LIGHT) && !defined(USE_FAST_LIGHT)\r\n\tgl_FragColor.rgb += specular."
+"rgb;\r\n#endif\r\n\r\n\tgl_FragColor *= var_Color;\r\n}\r\n";
+
+static const char *fallbackShadowfillShader_vp =
+"attribute vec4 attr_Position;\r\nattribute vec3 attr_Normal;\r\nattribute"
+" vec4 attr_TexCoord0;\r\n\r\n//#if defined(USE_VERTEX_ANIMATION)\r\nattrib"
+"ute vec4 attr_Position2;\r\nattribute vec3 attr_Normal2;\r\n//#endif\r\n"
+"\r\n//#if defined(USE_DEFORM_VERTEXES)\r\nuniform int u_DeformGen;\r\nu"
+"niform float u_DeformParams[5];\r\n//#endif\r\n\r\nuniform float u_Tim"
+"e;\r\nuniform mat4 u_ModelViewProjectionMatrix;\r\n\r\nuniform mat4 u_"
+"ModelMatrix;\r\n\r\n//#if defined(USE_VERTEX_ANIMATION)\r\nuniform float "
+"u_VertexLerp;\r\n//#endif\r\n\r\nvarying vec3 var_Position;\r\n\r\nfloat"
+" triangle(float x)\r\n{\r\n\treturn max(1.0 - abs(x), 0);\r\n}\r\n\r\nfloat"
+" sawtooth(float x)\r\n{\r\n\treturn x - floor(x);\r\n}\r\n\r\nvec4 DeformPo"
+"sition(const vec4 pos, const vec3 normal, const vec2 st)\r\n{\r\n\tif (u_De"
+"formGen == 0)\r\n\t{\r\n\t\treturn pos;\r\n\t}\r\n\r\n\tfloat base = u"
+"_DeformParams[0];\r\n\tfloat amplitude = u_DeformParams[1];\r\n\tfloat phas"
+"e = u_DeformParams[2];\r\n\tfloat frequency = u_DeformParams[3];\r\n\tf"
+"loat spread = u_DeformParams[4];\r\n\t\t\r\n\tif (u_DeformGen <= DGEN_WA"
+"VE_INVERSE_SAWTOOTH)\r\n\t{\r\n\t\tphase += (pos.x + pos.y + pos.z) * sprea"
+"d;\r\n\t}\r\n\telse if (u_DeformGen == DGEN_BULGE)\r\n\t{\r\n\t\tphase *= M"
+"_PI * 0.25 * st.x;\r\n\t}\r\n\r\n\tfloat value = phase + (u_Time * frequenc"
+"y);\r\n\tfloat func;\r\n\r\n\tif (u_DeformGen == DGEN_WAVE_SIN)\r\n\t{\r\n"
+"\t\tfunc = sin(value * 2.0 * M_PI);\r\n\t}\r\n\telse if (u_DeformGen == DGE"
+"N_WAVE_SQUARE)\r\n\t{\r\n\t\tfunc = sign(sin(value * 2.0 * M_PI));\r\n\t}\r"
+"\n\telse if (u_DeformGen == DGEN_WAVE_TRIANGLE)\r\n\t{\r\n\t\tfunc = triang"
+"le(value);\r\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE_SAWTOOTH)\r\n\t{\r"
+"\n\t\tfunc = sawtooth(value);\r\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE"
+"_INVERSE_SAWTOOTH)\r\n\t{\r\n\t\tfunc = (1.0 - sawtooth(value));\r\n\t}\r\n"
+"\telse if (u_DeformGen == DGEN_BULGE)\r\n\t{\r\n\t\tfunc = sin(value);\r\n"
+"\t}\r\n\r\n\tvec4 deformed = pos;\r\n\tdeformed.xyz += normal * (base + fun"
+"c * amplitude);\r\n\r\n\treturn deformed;\r\n\r\n}\r\n\r\n\r\nvoid main()\r"
+"\n{\r\n\tvec4 position = mix(attr_Position, attr_Position2, u_VertexLerp);"
+"\r\n\tvec3 normal = normalize(mix(attr_Normal, attr_Normal2, u_VertexLerp))"
+";\r\n\r\n\tposition = DeformPosition(position, normal, attr_TexCoord0.st);"
+"\r\n\r\n\tgl_Position = u_ModelViewProjectionMatrix * position;\r\n\t\r\n\t"
+"var_Position = (u_ModelMatrix * position).xyz;\r\n}\r\n";
+
+static const char *fallbackShadowfillShader_fp =
+"uniform vec4 u_LightOrigin;\r\nuniform float u_LightRadius;\r\n\r\nvarying"
+" vec3 var_Position;\r\n\r\nvoid main()\r\n{\r\n#if defined(USE_DEPTH)\r\n"
+"\tfloat depth = length(u_LightOrigin.xyz - var_Position) / u_LightRadius;\r"
+"\n #if 0\r\n\t// 32 bit precision\r\n\tconst vec4 bitSh = vec4( 256 * 256 *"
+" 256, 256 * 256, 256, 1);\r\n\tconst vec4 bitMsk = vec4"
+"( 0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);\r\n\t\r\n\tvec4 c"
+"omp;\r\n\tcomp = depth * bitSh;\r\n\tcomp.xyz = fract(comp.xyz);\r\n\tcomp "
+"-= comp.xxyz * bitMsk;\r\n\tgl_FragColor = comp;\r\n #endif\r\n\r\n #if 1\r"
+"\n\t// 24 bit precision\r\n\tconst vec3 bitSh = vec3( 256 * 256, 25"
+"6, 1);\r\n\tconst vec3 bitMsk = vec3( 0, 1.0 / 256.0, 1.0 "
+"/ 256.0);\r\n\t\r\n\tvec3 comp;\r\n\tcomp = depth * bitSh;\r\n\tcomp.xy = f"
+"ract(comp.xy);\r\n\tcomp -= comp.xxy * bitMsk;\r\n\tgl_FragColor = vec4(com"
+"p, 1.0);\r\n #endif\r\n\r\n #if 0\r\n\t// 8 bit precision\r\n\tgl_FragColor"
+" = vec4(depth, depth, depth, 1);\r\n #endif\r\n#else\r\n\tgl_FragColor = ve"
+"c4(0, 0, 0, 1);\r\n#endif\r\n}\r\n";
+
+static const char *fallbackPshadowShader_vp =
+"attribute vec4 attr_Position;\r\nattribute vec3 attr_Normal;\r\n\r\nuniform"
+" mat4 u_ModelViewProjectionMatrix;\r\nvarying vec3 var_Position;\r\nvar"
+"ying vec3 var_Normal;\r\n\r\n\r\nvoid main()\r\n{\r\n\tvec4 position = a"
+"ttr_Position;\r\n\r\n\tgl_Position = u_ModelViewProjectionMatrix * position"
+";\r\n\r\n\tvar_Position = position.xyz;\r\n\tvar_Normal = attr_Normal;"
+"\r\n}\r\n";
+
+static const char *fallbackPshadowShader_fp =
+"uniform sampler2D u_ShadowMap;\r\n\r\nuniform vec3 u_LightForward;\r\n"
+"uniform vec3 u_LightUp;\r\nuniform vec3 u_LightRight;\r\nuniform "
+"vec4 u_LightOrigin;\r\nuniform float u_LightRadius;\r\nvarying vec"
+"3 var_Position;\r\nvarying vec3 var_Normal;\r\n\r\nfloat sampleDi"
+"stMap(sampler2D texMap, vec2 uv, float scale)\r\n{\r\n\tvec3 distv = textur"
+"e2D(texMap, uv).xyz;\r\n\treturn dot(distv, vec3(1.0 / (256.0 * 256.0), 1.0"
+" / 256.0, 1.0)) * scale;\r\n}\r\n\r\nvoid main()\r\n{\r\n\tvec3 lightToPos "
+"= var_Position - u_LightOrigin.xyz;\r\n\tvec2 st = vec2(-dot(u_LightRight, "
+"lightToPos), dot(u_LightUp, lightToPos));\r\n\t\r\n\tfloat fade = length(st"
+");\r\n\t\r\n#if defined(USE_DISCARD)\r\n\tif (fade >= 1.0)\r\n\t{\r\n\t\tdi"
+"scard;\r\n\t}\r\n#endif\r\n\r\n\tfade = clamp(8.0 - fade * 8.0, 0.0, 1.0);"
+"\r\n\t\r\n\tst = st * 0.5 + vec2(0.5);\r\n\r\n#if defined(USE_SOLID_PSHADOW"
+"S)\r\n\tfloat intensity = max(sign(u_LightRadius - length(lightToPos)), 0.0"
+");\r\n#else\r\n\tfloat intensity = clamp((1.0 - dot(lightToPos, lightToPos)"
+" / (u_LightRadius * u_LightRadius)) * 2.0, 0.0, 1.0);\r\n#endif\r\n\t\r\n\t"
+"float lightDist = length(lightToPos);\r\n\tfloat dist;\r\n\r\n#if defined(U"
+"SE_DISCARD)\r\n\tif (dot(u_LightForward, lightToPos) <= 0.0)\r\n\t{\r\n\t\t"
+"discard;\r\n\t}\r\n\r\n\tif (dot(var_Normal, lightToPos) > 0.0)\r\n\t{\r\n"
+"\t\tdiscard;\r\n\t}\r\n#else\r\n\tintensity *= max(sign(dot(u_LightForward,"
+" lightToPos)), 0.0);\r\n\tintensity *= max(sign(-dot(var_Normal, lightToPos"
+")), 0.0);\r\n#endif\r\n\r\n\tintensity *= fade;\r\n#if defined(USE_PCF)\r\n"
+"\tfloat part;\r\n\t\r\n\tdist = sampleDistMap(u_ShadowMap, st + vec2(-1.0/5"
+"12.0, -1.0/512.0), u_LightRadius);\r\n\tpart = max(sign(lightDist - dist),"
+" 0.0);\r\n\r\n\tdist = sampleDistMap(u_ShadowMap, st + vec2( 1.0/512.0, -1."
+"0/512.0), u_LightRadius);\r\n\tpart += max(sign(lightDist - dist), 0.0);\r"
+"\n\r\n\tdist = sampleDistMap(u_ShadowMap, st + vec2(-1.0/512.0, 1.0/512.0)"
+", u_LightRadius);\r\n\tpart += max(sign(lightDist - dist), 0.0);\r\n\r\n\td"
+"ist = sampleDistMap(u_ShadowMap, st + vec2( 1.0/512.0, 1.0/512.0), u_Light"
+"Radius);\r\n\tpart += max(sign(lightDist - dist), 0.0);\r\n\r\n #if define"
+"d(USE_DISCARD)\r\n\tif (part <= 0.0)\r\n\t{\r\n\t\tdiscard;\r\n\t}\r\n #en"
+"dif\r\n\r\n\tintensity *= part * 0.25;\r\n#else\r\n\tdist = sampleDistMap(u"
+"_ShadowMap, st, u_LightRadius);\r\n\r\n #if defined(USE_DISCARD)\r\n\tif ("
+"lightDist - dist <= 0.0)\r\n\t{\r\n\t\tdiscard;\r\n\t}\r\n #endif\r\n\t\t"
+"\t\r\n\tintensity *= max(sign(lightDist - dist), 0.0);\r\n#endif\r\n\t\t\r"
+"\n\tgl_FragColor.rgb = vec3(0);\r\n\tgl_FragColor.a = clamp(intensity, 0.0,"
+" 0.75);\r\n}\r\n";
+
+static const char *fallbackDown4xShader_vp =
+"attribute vec4 attr_Position;\r\nattribute vec4 attr_TexCoord0;\r\n\r\nunif"
+"orm mat4 u_ModelViewProjectionMatrix;\r\n\r\nvarying vec2 var_TexCoords"
+";\r\n\r\n\r\nvoid main()\r\n{\r\n\tgl_Position = u_ModelViewProjectionMatri"
+"x * attr_Position;\r\n\tvar_TexCoords = attr_TexCoord0.st;\r\n}\r\n";
+
+static const char *fallbackDown4xShader_fp =
+"uniform sampler2D u_TextureMap;\r\n\r\nuniform vec2 u_InvTexRes;\r\nva"
+"rying vec2 var_TexCoords;\r\n\r\nvoid main()\r\n{\r\n\tvec4 color;\r\n"
+"\tvec2 tc;\r\n\t\r\n\ttc = var_TexCoords + u_InvTexRes * vec2(-1.5, -1.5); "
+" color = texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRe"
+"s * vec2(-0.5, -1.5); color += texture2D(u_TextureMap, tc);\r\n\ttc = var_"
+"TexCoords + u_InvTexRes * vec2( 0.5, -1.5); color += texture2D(u_TextureMa"
+"p, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( 1.5, -1.5); color +="
+" texture2D(u_TextureMap, tc);\r\n\r\n\ttc = var_TexCoords + u_InvTexRes * v"
+"ec2(-1.5, -0.5); color += texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoo"
+"rds + u_InvTexRes * vec2(-0.5, -0.5); color += texture2D(u_TextureMap, tc);"
+"\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( 0.5, -0.5); color += texture"
+"2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( 1.5, -0"
+".5); color += texture2D(u_TextureMap, tc);\r\n\r\n\ttc = var_TexCoords + u_"
+"InvTexRes * vec2(-1.5, 0.5); color += texture2D(u_TextureMap, tc);\r\n\ttc"
+" = var_TexCoords + u_InvTexRes * vec2(-0.5, 0.5); color += texture2D(u_Tex"
+"tureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( 0.5, 0.5); col"
+"or += texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * "
+"vec2( 1.5, 0.5); color += texture2D(u_TextureMap, tc);\r\n\r\n\ttc = var_T"
+"exCoords + u_InvTexRes * vec2(-1.5, 1.5); color += texture2D(u_TextureMap"
+", tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2(-0.5, 1.5); color += "
+"texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( "
+"0.5, 1.5); color += texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords "
+"+ u_InvTexRes * vec2( 1.5, 1.5); color += texture2D(u_TextureMap, tc);\r"
+"\n\t\r\n\tcolor *= 0.0625;\r\n\t\r\n\tgl_FragColor = color;\r\n}\r\n";
+
+static const char *fallbackBokehShader_vp =
+"attribute vec4 attr_Position;\r\nattribute vec4 attr_TexCoord0;\r\n\r\nunif"
+"orm mat4 u_ModelViewProjectionMatrix;\r\n\r\nvarying vec2 var_TexCoords"
+";\r\n\r\n\r\nvoid main()\r\n{\r\n\tgl_Position = u_ModelViewProjectionMatri"
+"x * attr_Position;\r\n\tvar_TexCoords = attr_TexCoord0.st;\r\n}\r\n";
+
+static const char *fallbackBokehShader_fp =
+"uniform sampler2D u_TextureMap;\r\n\r\nuniform vec4 u_Color;\r\n\r\nun"
+"iform vec2 u_InvTexRes;\r\nvarying vec2 var_TexCoords;\r\n\r\nvoi"
+"d main()\r\n{\r\n\tvec4 color;\r\n\tvec2 tc;\r\n\r\n#if 0\r\n\tfloat c[7] ="
+" float[7](1.0, 0.9659258263, 0.8660254038, 0.7071067812, 0.5, 0.2588190451,"
+" 0.0);\r\n\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( c[0], c[6]); co"
+"lor = texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes *"
+" vec2( c[1], c[5]); color += texture2D(u_TextureMap, tc);\r\n\ttc = var_"
+"TexCoords + u_InvTexRes * vec2( c[2], c[4]); color += texture2D(u_Textur"
+"eMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( c[3], c[3]); co"
+"lor += texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes *"
+" vec2( c[4], c[2]); color += texture2D(u_TextureMap, tc);\r\n\ttc = var_"
+"TexCoords + u_InvTexRes * vec2( c[5], c[1]); color += texture2D(u_Textur"
+"eMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( c[6], c[0]); co"
+"lor += texture2D(u_TextureMap, tc);\r\n\r\n\ttc = var_TexCoords + u_InvTexR"
+"es * vec2( c[1], -c[5]); color += texture2D(u_TextureMap, tc);\r\n\ttc = "
+"var_TexCoords + u_InvTexRes * vec2( c[2], -c[4]); color += texture2D(u_Te"
+"xtureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( c[3], -c[3]);"
+" color += texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexR"
+"es * vec2( c[4], -c[2]); color += texture2D(u_TextureMap, tc);\r\n\ttc = "
+"var_TexCoords + u_InvTexRes * vec2( c[5], -c[1]); color += texture2D(u_Te"
+"xtureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( c[6], -c[0]);"
+" color += texture2D(u_TextureMap, tc);\r\n\r\n\ttc = var_TexCoords + u_Inv"
+"TexRes * vec2( -c[0], c[6]); color += texture2D(u_TextureMap, tc);\r\n\tt"
+"c = var_TexCoords + u_InvTexRes * vec2( -c[1], c[5]); color += texture2D("
+"u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( -c[2], c["
+"4]); color += texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_Inv"
+"TexRes * vec2( -c[3], c[3]); color += texture2D(u_TextureMap, tc);\r\n\tt"
+"c = var_TexCoords + u_InvTexRes * vec2( -c[4], c[2]); color += texture2D("
+"u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( -c[5], c["
+"1]); color += texture2D(u_TextureMap, tc);\r\n\r\n\ttc = var_TexCoords + u"
+"_InvTexRes * vec2( -c[1], -c[5]); color += texture2D(u_TextureMap, tc);\r"
+"\n\ttc = var_TexCoords + u_InvTexRes * vec2( -c[2], -c[4]); color += textu"
+"re2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( -c[3]"
+", -c[3]); color += texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + "
+"u_InvTexRes * vec2( -c[4], -c[2]); color += texture2D(u_TextureMap, tc);\r"
+"\n\ttc = var_TexCoords + u_InvTexRes * vec2( -c[5], -c[1]); color += textu"
+"re2D(u_TextureMap, tc);\r\n\t\r\n\tgl_FragColor = color * 0.04166667 * u_Co"
+"lor;\r\n#endif\r\n\r\n\tfloat c[5] = float[5](1.0, 0.9238795325, 0.70710678"
+"12, 0.3826834324, 0.0);\r\n\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( "
+"c[0], c[4]); color = texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoord"
+"s + u_InvTexRes * vec2( c[1], c[3]); color += texture2D(u_TextureMap, tc"
+");\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( c[2], c[2]); color += t"
+"exture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( "
+"c[3], c[1]); color += texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoord"
+"s + u_InvTexRes * vec2( c[4], c[0]); color += texture2D(u_TextureMap, tc"
+");\r\n\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( c[1], -c[3]); color "
+"+= texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec"
+"2( c[2], -c[2]); color += texture2D(u_TextureMap, tc);\r\n\ttc = var_TexC"
+"oords + u_InvTexRes * vec2( c[3], -c[1]); color += texture2D(u_TextureMap"
+", tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( c[4], -c[0]); color "
+"+= texture2D(u_TextureMap, tc);\r\n\r\n\ttc = var_TexCoords + u_InvTexRes *"
+" vec2( -c[0], c[4]); color += texture2D(u_TextureMap, tc);\r\n\ttc = var_"
+"TexCoords + u_InvTexRes * vec2( -c[1], c[3]); color += texture2D(u_Textur"
+"eMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( -c[2], c[2]); co"
+"lor += texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes *"
+" vec2( -c[3], c[1]); color += texture2D(u_TextureMap, tc);\r\n\r\n\ttc = "
+"var_TexCoords + u_InvTexRes * vec2( -c[1], -c[3]); color += texture2D(u_Te"
+"xtureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( -c[2], -c[2]);"
+" color += texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexR"
+"es * vec2( -c[3], -c[1]); color += texture2D(u_TextureMap, tc);\r\n\t\r\n"
+"\tgl_FragColor = color * 0.0625 * u_Color;\r\n}\r\n";
+
+static const char *fallbackToneMapShader_vp =
+"attribute vec4 attr_Position;\r\nattribute vec4 attr_TexCoord0;\r\n\r\nunif"
+"orm mat4 u_ModelViewProjectionMatrix;\r\n\r\nvarying vec2 var_TexCoords"
+";\r\n\r\n\r\nvoid main()\r\n{\r\n\tgl_Position = u_ModelViewProjectionMatri"
+"x * attr_Position;\r\n\tvar_TexCoords = attr_TexCoord0.st;\r\n}\r\n";
+
+static const char *fallbackToneMapShader_fp =
+"uniform sampler2D u_TextureMap;\r\nuniform sampler2D u_LevelsMap;\r\n\r\nun"
+"iform vec4 u_Color;\r\n\r\nuniform vec2 u_AutoExposureMinMax;\r\n"
+"uniform vec3 u_ToneMinAvgMaxLinear;\r\n\r\nvarying vec2 var_TexCo"
+"ords;\r\n\r\nconst vec3 LUMINANCE_VECTOR = vec3(0.2125, 0.7154, 0.0721);"
+" //vec3(0.299, 0.587, 0.114);\r\n\r\nvec3 FilmicTonemap(vec3 x)\r\n{\r\n\tc"
+"onst float SS = 0.22; // Shoulder Strength\r\n\tconst float LS = 0.30; //"
+" Linear Strength\r\n\tconst float LA = 0.10; // Linear Angle\r\n\tconst fl"
+"oat TS = 0.20; // Toe Strength\r\n\tconst float TAN = 0.01; // Toe Angle N"
+"umerator\r\n\tconst float TAD = 0.30; // Toe Angle Denominator\r\n\t\r\n\tv"
+"ec3 SSxx = SS * x * x;\r\n\tvec3 LSx = LS * x;\r\n\tvec3 LALSx = LSx * LA;"
+"\r\n\t\r\n\treturn ((SSxx + LALSx + TS * TAN) / (SSxx + LSx + TS * TAD)) - "
+"TAN / TAD;\r\n\r\n\t//return ((x*(SS*x+LA*LS)+TS*TAN)/(x*(SS*x+LS)+TS*TAD))"
+" - TAN/TAD;\r\n\r\n}\r\n\r\nvoid main()\r\n{\r\n\tvec4 color = texture2D(u_"
+"TextureMap, var_TexCoords) * u_Color;\r\n\tvec3 minAvgMax = texture2D(u_Lev"
+"elsMap, var_TexCoords).rgb;\r\n\tvec3 logMinAvgMaxLum = clamp(minAvgMax * 2"
+"0.0 - 10.0, -u_AutoExposureMinMax.y, -u_AutoExposureMinMax.x);\r\n\t\t\r\n"
+"\tfloat avgLum = exp2(logMinAvgMaxLum.y);\r\n\t//float maxLum = exp2(logMin"
+"AvgMaxLum.z);\r\n\r\n\tcolor.rgb *= u_ToneMinAvgMaxLinear.y / avgLum;\r\n\t"
+"color.rgb = max(vec3(0.0), color.rgb - vec3(u_ToneMinAvgMaxLinear.x));\r\n"
+"\r\n\tvec3 fWhite = 1.0 / FilmicTonemap(vec3(u_ToneMinAvgMaxLinear.z - u_To"
+"neMinAvgMaxLinear.x));\r\n\tcolor.rgb = FilmicTonemap(color.rgb) * fWhite;"
+"\r\n\t\r\n\tgl_FragColor = clamp(color, 0.0, 1.0);\r\n}\r\n";
+
+static const char *fallbackCalcLevels4xShader_vp =
+"attribute vec4 attr_Position;\r\nattribute vec4 attr_TexCoord0;\r\n\r\nunif"
+"orm mat4 u_ModelViewProjectionMatrix;\r\n\r\nvarying vec2 var_TexCoords"
+";\r\n\r\n\r\nvoid main()\r\n{\r\n\tgl_Position = u_ModelViewProjectionMatri"
+"x * attr_Position;\r\n\tvar_TexCoords = attr_TexCoord0.st;\r\n}\r\n";
+
+static const char *fallbackCalcLevels4xShader_fp =
+"uniform sampler2D u_TextureMap;\r\n\r\nuniform vec4 u_Color;\r\n\r\nun"
+"iform vec2 u_InvTexRes;\r\nvarying vec2 var_TexCoords;\r\n\r\ncon"
+"st vec3 LUMINANCE_VECTOR = vec3(0.2125, 0.7154, 0.0721); //vec3(0.299, 0"
+".587, 0.114);\r\n\r\nvec3 GetValues(vec2 offset, vec3 current)\r\n{\r\n\tve"
+"c3 minAvgMax;\r\n\tvec2 tc = var_TexCoords + u_InvTexRes * offset; minAvgMa"
+"x = texture2D(u_TextureMap, tc).rgb;\r\n\r\n#ifdef FIRST_PASS\r\n\tfloat lu"
+"mi = max(dot(LUMINANCE_VECTOR, minAvgMax), 0.000001);\r\n\tfloat loglumi = "
+"clamp(log2(lumi), -10.0, 10.0);\r\n\tminAvgMax = vec3(loglumi * 0.05 + 0.5)"
+";\r\n#endif\r\n\r\n\treturn vec3(min(current.x, minAvgMax.x), current.y + m"
+"inAvgMax.y, max(current.z, minAvgMax.z));\r\n}\r\n\r\nvoid main()\r\n{\r\n"
+"\tvec3 current = vec3(1.0, 0.0, 0.0);\r\n\r\n#ifdef FIRST_PASS\r\n\tcurrent"
+" = GetValues(vec2( 0.0, 0.0), current);\r\n#else\r\n\tcurrent = GetValues("
+"vec2(-1.5, -1.5), current);\r\n\tcurrent = GetValues(vec2(-0.5, -1.5), curr"
+"ent);\r\n\tcurrent = GetValues(vec2( 0.5, -1.5), current);\r\n\tcurrent = G"
+"etValues(vec2( 1.5, -1.5), current);\r\n\t\r\n\tcurrent = GetValues(vec2(-1"
+".5, -0.5), current);\r\n\tcurrent = GetValues(vec2(-0.5, -0.5), current);\r"
+"\n\tcurrent = GetValues(vec2( 0.5, -0.5), current);\r\n\tcurrent = GetValue"
+"s(vec2( 1.5, -0.5), current);\r\n\t\r\n\tcurrent = GetValues(vec2(-1.5, 0."
+"5), current);\r\n\tcurrent = GetValues(vec2(-0.5, 0.5), current);\r\n\tcur"
+"rent = GetValues(vec2( 0.5, 0.5), current);\r\n\tcurrent = GetValues(vec2("
+" 1.5, 0.5), current);\r\n\r\n\tcurrent = GetValues(vec2(-1.5, 1.5), curre"
+"nt);\r\n\tcurrent = GetValues(vec2(-0.5, 1.5), current);\r\n\tcurrent = Ge"
+"tValues(vec2( 0.5, 1.5), current);\r\n\tcurrent = GetValues(vec2( 1.5, 1."
+"5), current);\r\n\r\n\tcurrent.y *= 0.0625;\r\n#endif\r\n\r\n\tgl_FragColor"
+" = vec4(current, 1.0f);\r\n}\r\n";
+
+static const char *fallbackShadowmaskShader_vp =
+"attribute vec4 attr_Position;\r\nattribute vec4 attr_TexCoord0;\r\n\r\nunif"
+"orm vec3 u_ViewForward;\r\nuniform vec3 u_ViewLeft;\r\nuniform vec3 u"
+"_ViewUp;\r\nuniform vec4 u_ViewInfo; // zfar / znear\r\n\r\nvarying vec2 "
+" var_ScreenTex;\r\nvarying vec3 var_ViewDir;\r\n\r\nvoid main()\r\n{\r\n"
+"\tgl_Position = attr_Position;\r\n\t//vec2 screenCoords = gl_Position.xy / "
+"gl_Position.w;\r\n\t//var_ScreenTex = screenCoords * 0.5 + 0.5;\r\n\tvar_Sc"
+"reenTex = attr_TexCoord0.xy;\r\n\tvec2 screenCoords = attr_TexCoord0.xy * 2"
+".0 - 1.0;\r\n\tvar_ViewDir = u_ViewForward + u_ViewLeft * -screenCoords.x +"
+" u_ViewUp * screenCoords.y;\r\n}\r\n";
+
+static const char *fallbackShadowmaskShader_fp =
+"uniform sampler2D u_ScreenDepthMap;\r\n\r\nuniform sampler2D u_ShadowMap;\r"
+"\n#if defined(USE_SHADOW_CASCADE)\r\nuniform sampler2D u_ShadowMap2;\r\nuni"
+"form sampler2D u_ShadowMap3;\r\n#endif\r\n\r\nuniform mat4 u_ShadowMvp"
+";\r\n#if defined(USE_SHADOW_CASCADE)\r\nuniform mat4 u_ShadowMvp2;\r\n"
+"uniform mat4 u_ShadowMvp3;\r\n#endif\r\n\r\nuniform vec3 u_ViewOrigi"
+"n;\r\nuniform vec4 u_ViewInfo; // zfar / znear, zfar\r\n\r\nvarying vec2 "
+" var_ScreenTex;\r\nvarying vec3 var_ViewDir;\r\n\r\n// Input: It uses te"
+"xture coords as the random number seed.\r\n// Output: Random number: [0,1),"
+" that is between 0.0 and 0.999999... inclusive.\r\n// Author: Michael Pohor"
+"eski\r\n// Copyright: Copyleft 2012 :-)\r\n// Source: http://stackoverflow."
+"com/questions/5149544/can-i-generate-a-random-number-inside-a-pixel-shader"
+"\r\n\r\nfloat random( const vec2 p )\r\n{\r\n // We need irrationals for p"
+"seudo randomness.\r\n // Most (all?) known transcendental numbers will (ge"
+"nerally) work.\r\n const vec2 r = vec2(\r\n 23.1406926327792690, // e^"
+"pi (Gelfond's constant)\r\n 2.6651441426902251); // 2^sqrt(2) (Gelfond–"
+"Schneider constant)\r\n //return fract( cos( mod( 123456789., 1e-7 + 256. "
+"* dot(p,r) ) ) );\r\n return mod( 123456789., 1e-7 + 256. * dot(p,r) ); "
+"\r\n}\r\n\r\nfloat PCF(const sampler2D shadowmap, const vec2 st, const floa"
+"t dist)\r\n{\r\n\tfloat mult;\r\n\tfloat scale = 2.0 / r_shadowMapSize;\r\n"
+"\t\t\r\n#if defined(USE_SHADOW_FILTER)\r\n\tfloat r = random(var_ScreenTex."
+"xy);\r\n\tfloat sinr = sin(r) * scale;\r\n\tfloat cosr = cos(r) * scale;\r"
+"\n\tmat2 rmat = mat2(cosr, sinr, -sinr, cosr);\r\n\r\n\tmult = step(dist, "
+"texture2D(shadowmap, st + rmat * vec2(-0.7055767, 0.196515)).r);\r\n\tmult "
+"+= step(dist, texture2D(shadowmap, st + rmat * vec2(0.3524343, -0.7791386))"
+".r);\r\n\tmult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.239105"
+"6, 0.9189604)).r);\r\n #if defined(USE_SHADOW_FILTER2)\r\n\tmult += step(d"
+"ist, texture2D(shadowmap, st + rmat * vec2(-0.07580382, -0.09224417)).r);\r"
+"\n\tmult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.5784913, -0."
+"002528916)).r);\r\n\tmult += step(dist, texture2D(shadowmap, st + rmat * ve"
+"c2(0.192888, 0.4064181)).r);\r\n\tmult += step(dist, texture2D(shadowmap, s"
+"t + rmat * vec2(-0.6335801, -0.5247476)).r);\r\n\tmult += step(dist, textur"
+"e2D(shadowmap, st + rmat * vec2(-0.5579782, 0.7491854)).r);\r\n\tmult += st"
+"ep(dist, texture2D(shadowmap, st + rmat * vec2(0.7320465, 0.6317794)).r);\r"
+"\n\r\n\tmult *= 0.11111;\r\n #else\r\n mult *= 0.33333;\r\n #endif\r\n"
+"#else\r\n\tmult = step(dist, texture2D(shadowmap, st).r);\r\n#endif\r\n\t\t"
+"\r\n\treturn mult;\r\n}\r\n\r\nfloat getLinearDepth(sampler2D depthMap, vec"
+"2 tex, float zFarDivZNear)\r\n{\r\n\t\tfloat sampleZDivW = texture2D(depthM"
+"ap, tex).r;\r\n\t\treturn 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW);\r\n}\r"
+"\n\r\nvoid main()\r\n{\r\n\tfloat result;\r\n\t\r\n\tfloat depth = getLinea"
+"rDepth(u_ScreenDepthMap, var_ScreenTex, u_ViewInfo.x);\r\n\tfloat sampleZ ="
+" u_ViewInfo.y * depth;\r\n\r\n\tvec4 biasPos = vec4(u_ViewOrigin + var_View"
+"Dir * depth * 0.99, 1.0);\r\n\t\r\n\tvec4 shadowpos = u_ShadowMvp * biasPos"
+";\r\n\t\r\n#if defined(USE_SHADOW_CASCADE)\r\n\tconst float fadeTo = 0.5;\r"
+"\n\tresult = fadeTo;\r\n#else\r\n\tresult = 0.0;\r\n#endif\r\n\r\n\tif (all"
+"(lessThanEqual(abs(shadowpos.xyz), vec3(abs(shadowpos.w)))))\r\n\t{\r\n\t\t"
+"shadowpos.xyz = shadowpos.xyz / shadowpos.w * 0.5 + 0.5;\r\n\t\tresult = PC"
+"F(u_ShadowMap, shadowpos.xy, shadowpos.z);\r\n\t}\r\n#if defined(USE_SHADOW"
+"_CASCADE)\r\n\telse\r\n\t{\r\n\t\tshadowpos = u_ShadowMvp2 * biasPos;\r\n\r"
+"\n\t\tif (all(lessThanEqual(abs(shadowpos.xyz), vec3(abs(shadowpos.w)))))\r"
+"\n\t\t{\r\n\t\t\tshadowpos.xyz = shadowpos.xyz / shadowpos.w * 0.5 + 0.5;\r"
+"\n\t\t\tresult = PCF(u_ShadowMap2, shadowpos.xy, shadowpos.z);\r\n\t\t}\r\n"
+"\t\telse\r\n\t\t{\r\n\t\t\tshadowpos = u_ShadowMvp3 * biasPos;\r\n\r\n\t\t"
+"\tif (all(lessThanEqual(abs(shadowpos.xyz), vec3(abs(shadowpos.w)))))\r\n\t"
+"\t\t{\r\n\t\t\t\tshadowpos.xyz = shadowpos.xyz / shadowpos.w * 0.5 + 0.5;\r"
+"\n\t\t\t\tresult = PCF(u_ShadowMap3, shadowpos.xy, shadowpos.z);\r\n\r\n\t"
+"\t\t\tfloat fade = clamp(sampleZ / r_shadowCascadeZFar * 10.0 - 9.0, 0.0, 1"
+".0);\r\n\t\t\t\tresult = mix(result, fadeTo, fade);\r\n\t\t\t}\r\n\t\t}\r\n"
+"\t}\r\n#endif\r\n\t\t\r\n\tgl_FragColor = vec4(vec3(result), 1.0);\r\n}\r\n";
+
+static const char *fallbackSsaoShader_vp =
+"attribute vec4 attr_Position;\r\nattribute vec4 attr_TexCoord0;\r\n\r\nvary"
+"ing vec2 var_ScreenTex;\r\n\r\nvoid main()\r\n{\r\n\tgl_Position = attr_P"
+"osition;\r\n\tvar_ScreenTex = attr_TexCoord0.xy;\r\n\t//vec2 screenCoords ="
+" gl_Position.xy / gl_Position.w;\r\n\t//var_ScreenTex = screenCoords * 0.5 "
+"+ 0.5;\r\n}\r\n";
+
+static const char *fallbackSsaoShader_fp =
+"uniform sampler2D u_ScreenDepthMap;\r\n\r\nuniform vec4 u_ViewInfo; // zf"
+"ar / znear, zfar\r\n\r\nvarying vec2 var_ScreenTex;\r\n\r\nvec2 poissonDi"
+"sc[9] = vec2[9](\r\nvec2(-0.7055767, 0.196515), vec2(0.3524343, -0.77913"
+"86),\r\nvec2(0.2391056, 0.9189604), vec2(-0.07580382, -0.09224417),\r\nv"
+"ec2(0.5784913, -0.002528916), vec2(0.192888, 0.4064181),\r\nvec2(-0.6335801"
+", -0.5247476), vec2(-0.5579782, 0.7491854),\r\nvec2(0.7320465, 0.6317794)"
+"\r\n);\r\n\r\n// Input: It uses texture coords as the random number seed.\r"
+"\n// Output: Random number: [0,1), that is between 0.0 and 0.999999... incl"
+"usive.\r\n// Author: Michael Pohoreski\r\n// Copyright: Copyleft 2012 :-)\r"
+"\n// Source: http://stackoverflow.com/questions/5149544/can-i-generate-a-ra"
+"ndom-number-inside-a-pixel-shader\r\n\r\nfloat random( const vec2 p )\r\n{"
+"\r\n // We need irrationals for pseudo randomness.\r\n // Most (all?) kno"
+"wn transcendental numbers will (generally) work.\r\n const vec2 r = vec2("
+"\r\n 23.1406926327792690, // e^pi (Gelfond's constant)\r\n 2.665144"
+"1426902251); // 2^sqrt(2) (Gelfond–Schneider constant)\r\n //return fract("
+" cos( mod( 123456789., 1e-7 + 256. * dot(p,r) ) ) );\r\n return mod( 12345"
+"6789., 1e-7 + 256. * dot(p,r) ); \r\n}\r\n\r\nmat2 randomRotation( const v"
+"ec2 p )\r\n{\r\n\tfloat r = random(p);\r\n\tfloat sinr = sin(r);\r\n\tfloat"
+" cosr = cos(r);\r\n\treturn mat2(cosr, sinr, -sinr, cosr);\r\n}\r\n\r\nfloa"
+"t getLinearDepth(sampler2D depthMap, const vec2 tex, const float zFarDivZNe"
+"ar)\r\n{\r\n\t\tfloat sampleZDivW = texture2D(depthMap, tex).r;\r\n\t\tretu"
+"rn 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW);\r\n}\r\n\r\nfloat ambientOccl"
+"usion(sampler2D depthMap, const vec2 tex, const float zFarDivZNear, const f"
+"loat zFar)\r\n{\r\n\tfloat result = 0;\r\n\r\n\tfloat sampleZ = zFar * getL"
+"inearDepth(depthMap, tex, zFarDivZNear);\r\n\r\n\tvec2 expectedSlope = vec2"
+"(dFdx(sampleZ), dFdy(sampleZ)) / vec2(dFdx(tex.x), dFdy(tex.y));\r\n\t\r\n"
+"\tif (length(expectedSlope) > 5000.0)\r\n\t\treturn 1.0;\r\n\t\r\n\tvec2 of"
+"fsetScale = vec2(3.0 / sampleZ);\r\n\t\r\n\tmat2 rmat = randomRotation(tex)"
+";\r\n\t\t\r\n\tint i;\r\n\tfor (i = 0; i < 3; i++)\r\n\t{\r\n\t\tvec2 offse"
+"t = rmat * poissonDisc[i] * offsetScale;\r\n\t\tfloat sampleZ2 = zFar * get"
+"LinearDepth(depthMap, tex + offset, zFarDivZNear);\r\n\r\n\t\tif (abs(sampl"
+"eZ - sampleZ2) > 20.0)\r\n\t\t\tresult += 1.0;\r\n\t\telse\r\n\t\t{\r\n\t\t"
+"\tfloat expectedZ = sampleZ + dot(expectedSlope, offset);\r\n\t\t\tresult +"
+"= step(expectedZ - 1.0, sampleZ2);\r\n\t\t}\r\n\t}\r\n\t\r\n\tresult *= 0.3"
+"3333;\r\n\t\r\n\treturn result;\r\n}\r\n\r\nvoid main()\r\n{\r\n\tfloat res"
+"ult = ambientOcclusion(u_ScreenDepthMap, var_ScreenTex, u_ViewInfo.x, u_Vie"
+"wInfo.y);\r\n\t\t\t\r\n\tgl_FragColor = vec4(vec3(result), 1.0);\r\n}\r\n";
+
+static const char *fallbackDepthBlurShader_vp =
+"attribute vec4 attr_Position;\r\nattribute vec4 attr_TexCoord0;\r\n\r\nvary"
+"ing vec2 var_ScreenTex;\r\n\r\nvoid main()\r\n{\r\n\tgl_Position = attr_P"
+"osition;\r\n\tvar_ScreenTex = attr_TexCoord0.xy;\r\n\t//vec2 screenCoords ="
+" gl_Position.xy / gl_Position.w;\r\n\t//var_ScreenTex = screenCoords * 0.5 "
+"+ 0.5;\r\n}\r\n";
+
+static const char *fallbackDepthBlurShader_fp =
+"uniform sampler2D u_ScreenImageMap;\r\nuniform sampler2D u_ScreenDepthMap;"
+"\r\n\r\nuniform vec4 u_ViewInfo; // zfar / znear, zfar\r\nvarying vec2 "
+"var_ScreenTex;\r\n\r\n//float gauss[5] = float[5](0.30, 0.23, 0.097, 0.024,"
+" 0.0033);\r\nfloat gauss[4] = float[4](0.40, 0.24, 0.054, 0.0044);\r\n//flo"
+"at gauss[3] = float[3](0.60, 0.19, 0.0066);\r\n#define GAUSS_SIZE 4\r\n\r\n"
+"float getLinearDepth(sampler2D depthMap, const vec2 tex, const float zFarDi"
+"vZNear)\r\n{\r\n\t\tfloat sampleZDivW = texture2D(depthMap, tex).r;\r\n\t\t"
+"return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW);\r\n}\r\n\r\nvec4 depthGau"
+"ssian1D(sampler2D imageMap, sampler2D depthMap, vec2 tex, float zFarDivZNea"
+"r, float zFar)\r\n{\r\n\tfloat scale = 1.0 / 256.0;\r\n\r\n#if defined(USE_"
+"HORIZONTAL_BLUR)\r\n vec2 direction = vec2(1.0, 0.0) * scale;\r\n#else /"
+"/ if defined(USE_VERTICAL_BLUR)\r\n\tvec2 direction = vec2(0.0, 1.0) * scal"
+"e;\r\n#endif\r\n\t\r\n\tfloat depthCenter = zFar * getLinearDepth(depthMap,"
+" tex, zFarDivZNear);\r\n\tvec2 centerSlope = vec2(dFdx(depthCenter), dFdy(d"
+"epthCenter)) / vec2(dFdx(tex.x), dFdy(tex.y));\r\n\t\t\r\n\tvec4 result = t"
+"exture2D(imageMap, tex) * gauss[0];\r\n\tfloat total = gauss[0];\r\n\r\n\ti"
+"nt i, j;\r\n\tfor (i = 0; i < 2; i++)\r\n\t{\r\n\t\tfor (j = 1; j < GAUSS_S"
+"IZE; j++)\r\n\t\t{\r\n\t\t\tvec2 offset = direction * j;\r\n\t\t\tfloat dep"
+"thSample = zFar * getLinearDepth(depthMap, tex + offset, zFarDivZNear);\r\n"
+"\t\t\tfloat depthExpected = depthCenter + dot(centerSlope, offset);\r\n\t\t"
+"\tif(abs(depthSample - depthExpected) < 5.0)\r\n\t\t\t{\r\n\t\t\t\tresult +"
+"= texture2D(imageMap, tex + offset) * gauss[j];\r\n\t\t\t\ttotal += gauss[j"
+"];\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tdirection = -direction;\r\n\t}\t\r\n"
+"\t\t\r\n\treturn result / total;\r\n}\r\n\r\nvoid main()\r\n{\t\t\r\n\tgl_F"
+"ragColor = depthGaussian1D(u_ScreenImageMap, u_ScreenDepthMap, var_ScreenTe"
+"x, u_ViewInfo.x, u_ViewInfo.y);\r\n}\r\n";
+
+
+static void GLSL_PrintInfoLog(GLhandleARB object, qboolean developerOnly)
+{
+ char *msg;
+ static char msgPart[1024];
+ int maxLength = 0;
+ int i;
+ int printLevel = developerOnly ? PRINT_DEVELOPER : PRINT_ALL;
+
+ qglGetObjectParameterivARB(object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &maxLength);
+
+ if (maxLength <= 0)
+ {
+ ri.Printf(printLevel, "No compile log.\n");
+ return;
+ }
+
+ ri.Printf(printLevel, "compile log:\n");
+
+ if (maxLength < 1023)
+ {
+ qglGetInfoLogARB(object, maxLength, &maxLength, msgPart);
+
+ msgPart[maxLength + 1] = '\0';
+
+ ri.Printf(printLevel, "%s\n", msgPart);
+ }
+ else
+ {
+ msg = ri.Malloc(maxLength);
+
+ qglGetInfoLogARB(object, maxLength, &maxLength, msg);
+
+ for(i = 0; i < maxLength; i += 1024)
+ {
+ Q_strncpyz(msgPart, msg + i, sizeof(msgPart));
+
+ ri.Printf(printLevel, "%s\n", msgPart);
+ }
+
+ ri.Free(msg);
+ }
+}
+
+static void GLSL_PrintShaderSource(GLhandleARB object)
+{
+ char *msg;
+ static char msgPart[1024];
+ int maxLength = 0;
+ int i;
+
+ qglGetObjectParameterivARB(object, GL_OBJECT_SHADER_SOURCE_LENGTH_ARB, &maxLength);
+
+ msg = ri.Malloc(maxLength);
+
+ qglGetShaderSourceARB(object, maxLength, &maxLength, msg);
+
+ for(i = 0; i < maxLength; i += 1024)
+ {
+ Q_strncpyz(msgPart, msg + i, sizeof(msgPart));
+ ri.Printf(PRINT_ALL, "%s\n", msgPart);
+ }
+
+ ri.Free(msg);
+}
+
+static void GLSL_GetShaderHeader( GLenum shaderType, const GLcharARB *extra, char *dest, int size )
+{
+ float fbufWidthScale, fbufHeightScale;
+
+ dest[0] = '\0';
+
+ // HACK: abuse the GLSL preprocessor to turn GLSL 1.20 shaders into 1.30 ones
+ if(glRefConfig.glslMajorVersion > 1 || (glRefConfig.glslMajorVersion == 1 && glRefConfig.glslMinorVersion >= 30))
+ {
+ Q_strcat(dest, size, "#version 130\n");
+
+ if(shaderType == GL_VERTEX_SHADER_ARB)
+ {
+ Q_strcat(dest, size, "#define attribute in\n");
+ Q_strcat(dest, size, "#define varying out\n");
+ }
+ else
+ {
+ Q_strcat(dest, size, "#define varying in\n");
+
+ Q_strcat(dest, size, "out vec4 out_Color;\n");
+ Q_strcat(dest, size, "#define gl_FragColor out_Color\n");
+ }
+ }
+ else
+ {
+ Q_strcat(dest, size, "#version 120\n");
+ }
+
+ // HACK: add some macros to avoid extra uniforms and save speed and code maintenance
+ //Q_strcat(dest, size,
+ // va("#ifndef r_SpecularExponent\n#define r_SpecularExponent %f\n#endif\n", r_specularExponent->value));
+ //Q_strcat(dest, size,
+ // va("#ifndef r_SpecularScale\n#define r_SpecularScale %f\n#endif\n", r_specularScale->value));
+ //Q_strcat(dest, size,
+ // va("#ifndef r_NormalScale\n#define r_NormalScale %f\n#endif\n", r_normalScale->value));
+
+
+ Q_strcat(dest, size, "#ifndef M_PI\n#define M_PI 3.14159265358979323846f\n#endif\n");
+
+ //Q_strcat(dest, size, va("#ifndef MAX_SHADOWMAPS\n#define MAX_SHADOWMAPS %i\n#endif\n", MAX_SHADOWMAPS));
+
+ Q_strcat(dest, size,
+ va("#ifndef deformGen_t\n"
+ "#define deformGen_t\n"
+ "#define DGEN_WAVE_SIN %i\n"
+ "#define DGEN_WAVE_SQUARE %i\n"
+ "#define DGEN_WAVE_TRIANGLE %i\n"
+ "#define DGEN_WAVE_SAWTOOTH %i\n"
+ "#define DGEN_WAVE_INVERSE_SAWTOOTH %i\n"
+ "#define DGEN_BULGE %i\n"
+ "#define DGEN_MOVE %i\n"
+ "#endif\n",
+ DGEN_WAVE_SIN,
+ DGEN_WAVE_SQUARE,
+ DGEN_WAVE_TRIANGLE,
+ DGEN_WAVE_SAWTOOTH,
+ DGEN_WAVE_INVERSE_SAWTOOTH,
+ DGEN_BULGE,
+ DGEN_MOVE));
+
+ Q_strcat(dest, size,
+ va("#ifndef tcGen_t\n"
+ "#define tcGen_t\n"
+ "#define TCGEN_LIGHTMAP %i\n"
+ "#define TCGEN_TEXTURE %i\n"
+ "#define TCGEN_ENVIRONMENT_MAPPED %i\n"
+ "#define TCGEN_FOG %i\n"
+ "#define TCGEN_VECTOR %i\n"
+ "#endif\n",
+ TCGEN_LIGHTMAP,
+ TCGEN_TEXTURE,
+ TCGEN_ENVIRONMENT_MAPPED,
+ TCGEN_FOG,
+ TCGEN_VECTOR));
+
+ Q_strcat(dest, size,
+ va("#ifndef colorGen_t\n"
+ "#define colorGen_t\n"
+ "#define CGEN_LIGHTING_DIFFUSE %i\n"
+ "#endif\n",
+ CGEN_LIGHTING_DIFFUSE));
+
+ Q_strcat(dest, size,
+ va("#ifndef alphaGen_t\n"
+ "#define alphaGen_t\n"
+ "#define AGEN_LIGHTING_SPECULAR %i\n"
+ "#define AGEN_PORTAL %i\n"
+ "#define AGEN_FRESNEL %i\n"
+ "#endif\n",
+ AGEN_LIGHTING_SPECULAR,
+ AGEN_PORTAL,
+ AGEN_FRESNEL));
+
+ Q_strcat(dest, size,
+ va("#ifndef texenv_t\n"
+ "#define texenv_t\n"
+ "#define TEXENV_MODULATE %i\n"
+ "#define TEXENV_ADD %i\n"
+ "#define TEXENV_REPLACE %i\n"
+ "#endif\n",
+ GL_MODULATE,
+ GL_ADD,
+ GL_REPLACE));
+
+ fbufWidthScale = 1.0f / ((float)glConfig.vidWidth);
+ fbufHeightScale = 1.0f / ((float)glConfig.vidHeight);
+ Q_strcat(dest, size,
+ va("#ifndef r_FBufScale\n#define r_FBufScale vec2(%f, %f)\n#endif\n", fbufWidthScale, fbufHeightScale));
+
+ if (extra)
+ {
+ Q_strcat(dest, size, extra);
+ }
+
+ // OK we added a lot of stuff but if we do something bad in the GLSL shaders then we want the proper line
+ // so we have to reset the line counting
+ Q_strcat(dest, size, "#line 0\n");
+}
+
+static int GLSL_CompileGPUShader(GLhandleARB program, GLhandleARB *prevShader, const GLcharARB *buffer, int size, GLenum shaderType)
+{
+ GLint compiled;
+ GLhandleARB shader;
+
+ shader = qglCreateShaderObjectARB(shaderType);
+
+ qglShaderSourceARB(shader, 1, (const GLcharARB **)&buffer, &size);
+
+ // compile shader
+ qglCompileShaderARB(shader);
+
+ // check if shader compiled
+ qglGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled);
+ if(!compiled)
+ {
+ GLSL_PrintShaderSource(shader);
+ GLSL_PrintInfoLog(shader, qfalse);
+ ri.Error(ERR_DROP, "Couldn't compile shader");
+ return 0;
+ }
+
+ //GLSL_PrintInfoLog(shader, qtrue);
+ //GLSL_PrintShaderSource(shader);
+
+ if (*prevShader)
+ {
+ qglDetachObjectARB(program, *prevShader);
+ qglDeleteObjectARB(*prevShader);
+ }
+
+ // attach shader to program
+ qglAttachObjectARB(program, shader);
+
+ *prevShader = shader;
+
+ return 1;
+}
+
+
+static void GLSL_DumpText(const char *shaderText, int size, const char *name, GLenum shaderType)
+{
+ int i, l, inc;
+ ri.Printf(PRINT_ALL, "static const char *fallback%sShader_%s =\n\"", name, shaderType == GL_VERTEX_SHADER_ARB ? "vp" : "fp");
+ l = 0;
+
+ for (i = 0; i < size; i++)
+ {
+ switch (shaderText[i])
+ {
+ case '\a':
+ case '\b':
+ case '\f':
+ case '\n':
+ case '\r':
+ case '\t':
+ case '\v':
+ case '"':
+ case '\\':
+ inc = 2;
+ break;
+ default:
+ inc = 1;
+ break;
+ }
+
+ l += inc;
+
+ if (l >= 76)
+ {
+ ri.Printf(PRINT_ALL, "\"\n\"");
+ l = inc;
+ }
+
+ switch (shaderText[i])
+ {
+ case '\a':
+ ri.Printf(PRINT_ALL, "\\a");
+ break;
+ case '\b':
+ ri.Printf(PRINT_ALL, "\\b");
+ break;
+ case '\f':
+ ri.Printf(PRINT_ALL, "\\f");
+ break;
+ case '\n':
+ ri.Printf(PRINT_ALL, "\\n");
+ break;
+ case '\r':
+ ri.Printf(PRINT_ALL, "\\r");
+ break;
+ case '\t':
+ ri.Printf(PRINT_ALL, "\\t");
+ break;
+ case '\v':
+ ri.Printf(PRINT_ALL, "\\v");
+ break;
+ case '"':
+ ri.Printf(PRINT_ALL, "\\\"");
+ break;
+ case '\\':
+ ri.Printf(PRINT_ALL, "\\\\");
+ break;
+ default:
+ ri.Printf(PRINT_ALL, "%c", shaderText[i]);
+ break;
+ }
+ }
+ ri.Printf(PRINT_ALL, "\";\n\n");
+}
+
+static int GLSL_LoadGPUShaderText(const char *name, const char *fallback,
+ GLenum shaderType, char *dest, int destSize, qboolean dump)
+{
+ char filename[MAX_QPATH];
+ GLcharARB *buffer = NULL;
+ const GLcharARB *shaderText = NULL;
+ int size;
+ int result;
+
+ if(shaderType == GL_VERTEX_SHADER_ARB)
+ {
+ Com_sprintf(filename, sizeof(filename), "glsl/%s_vp.glsl", name);
+ }
+ else
+ {
+ Com_sprintf(filename, sizeof(filename), "glsl/%s_fp.glsl", name);
+ }
+
+ ri.Printf(PRINT_DEVELOPER, "...loading '%s'\n", filename);
+ size = ri.FS_ReadFile(filename, (void **)&buffer);
+ if(!buffer)
+ {
+ if (fallback)
+ {
+ ri.Printf(PRINT_DEVELOPER, "couldn't load, using fallback\n");
+ shaderText = fallback;
+ size = strlen(shaderText);
+ }
+ else
+ {
+ ri.Printf(PRINT_DEVELOPER, "couldn't load!\n");
+ return 0;
+ }
+ }
+ else
+ {
+ shaderText = buffer;
+ }
+
+ if (dump)
+ GLSL_DumpText(shaderText, size, name, shaderType);
+
+ if (size > destSize)
+ {
+ result = 0;
+ }
+ else
+ {
+ Q_strncpyz(dest, shaderText, size + 1);
+ result = 1;
+ }
+
+ if (buffer)
+ {
+ ri.FS_FreeFile(buffer);
+ }
+
+ return result;
+}
+
+static void GLSL_LinkProgram(GLhandleARB program)
+{
+ GLint linked;
+
+ qglLinkProgramARB(program);
+
+ qglGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &linked);
+ if(!linked)
+ {
+ GLSL_PrintInfoLog(program, qfalse);
+ ri.Error(ERR_DROP, "\nshaders failed to link");
+ }
+}
+
+static void GLSL_ValidateProgram(GLhandleARB program)
+{
+ GLint validated;
+
+ qglValidateProgramARB(program);
+
+ qglGetObjectParameterivARB(program, GL_OBJECT_VALIDATE_STATUS_ARB, &validated);
+ if(!validated)
+ {
+ GLSL_PrintInfoLog(program, qfalse);
+ ri.Error(ERR_DROP, "\nshaders failed to validate");
+ }
+}
+
+static void GLSL_ShowProgramUniforms(GLhandleARB program)
+{
+ int i, count, size;
+ GLenum type;
+ char uniformName[1000];
+
+ // install the executables in the program object as part of current state.
+ qglUseProgramObjectARB(program);
+
+ // check for GL Errors
+
+ // query the number of active uniforms
+ qglGetObjectParameterivARB(program, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &count);
+
+ // Loop over each of the active uniforms, and set their value
+ for(i = 0; i < count; i++)
+ {
+ qglGetActiveUniformARB(program, i, sizeof(uniformName), NULL, &size, &type, uniformName);
+
+ ri.Printf(PRINT_DEVELOPER, "active uniform: '%s'\n", uniformName);
+ }
+
+ qglUseProgramObjectARB(0);
+}
+
+static int GLSL_InitGPUShader2(shaderProgram_t * program, const char *name, int attribs, const char *vpCode, const char *fpCode, int numUniforms)
+{
+ ri.Printf(PRINT_DEVELOPER, "------- GPU shader -------\n");
+
+ if(strlen(name) >= MAX_QPATH)
+ {
+ ri.Error(ERR_DROP, "GLSL_InitGPUShader2: \"%s\" is too long\n", name);
+ }
+
+ Q_strncpyz(program->name, name, sizeof(program->name));
+
+ program->program = qglCreateProgramObjectARB();
+ program->attribs = attribs;
+
+ if (!(GLSL_CompileGPUShader(program->program, &program->vertexShader, vpCode, strlen(vpCode), GL_VERTEX_SHADER_ARB)))
+ {
+ ri.Printf(PRINT_ALL, "GLSL_InitGPUShader2: Unable to load \"%s\" as GL_VERTEX_SHADER_ARB\n", name);
+ qglDeleteObjectARB(program->program);
+ return 0;
+ }
+
+ if(fpCode)
+ {
+ if(!(GLSL_CompileGPUShader(program->program, &program->fragmentShader, fpCode, strlen(fpCode), GL_FRAGMENT_SHADER_ARB)))
+ {
+ ri.Printf(PRINT_ALL, "GLSL_InitGPUShader2: Unable to load \"%s\" as GL_FRAGMENT_SHADER_ARB\n", name);
+ qglDeleteObjectARB(program->program);
+ return 0;
+ }
+ }
+
+ if(attribs & ATTR_POSITION)
+ qglBindAttribLocationARB(program->program, ATTR_INDEX_POSITION, "attr_Position");
+
+ if(attribs & ATTR_TEXCOORD)
+ qglBindAttribLocationARB(program->program, ATTR_INDEX_TEXCOORD0, "attr_TexCoord0");
+
+ if(attribs & ATTR_LIGHTCOORD)
+ qglBindAttribLocationARB(program->program, ATTR_INDEX_TEXCOORD1, "attr_TexCoord1");
+
+// if(attribs & ATTR_TEXCOORD2)
+// qglBindAttribLocationARB(program->program, ATTR_INDEX_TEXCOORD2, "attr_TexCoord2");
+
+// if(attribs & ATTR_TEXCOORD3)
+// qglBindAttribLocationARB(program->program, ATTR_INDEX_TEXCOORD3, "attr_TexCoord3");
+
+#ifdef USE_VERT_TANGENT_SPACE
+ if(attribs & ATTR_TANGENT)
+ qglBindAttribLocationARB(program->program, ATTR_INDEX_TANGENT, "attr_Tangent");
+
+ if(attribs & ATTR_BITANGENT)
+ qglBindAttribLocationARB(program->program, ATTR_INDEX_BITANGENT, "attr_Bitangent");
+#endif
+
+ if(attribs & ATTR_NORMAL)
+ qglBindAttribLocationARB(program->program, ATTR_INDEX_NORMAL, "attr_Normal");
+
+ if(attribs & ATTR_COLOR)
+ qglBindAttribLocationARB(program->program, ATTR_INDEX_COLOR, "attr_Color");
+
+ if(attribs & ATTR_PAINTCOLOR)
+ qglBindAttribLocationARB(program->program, ATTR_INDEX_PAINTCOLOR, "attr_PaintColor");
+
+ if(attribs & ATTR_LIGHTDIRECTION)
+ qglBindAttribLocationARB(program->program, ATTR_INDEX_LIGHTDIRECTION, "attr_LightDirection");
+
+ if(attribs & ATTR_POSITION2)
+ qglBindAttribLocationARB(program->program, ATTR_INDEX_POSITION2, "attr_Position2");
+
+ if(attribs & ATTR_NORMAL2)
+ qglBindAttribLocationARB(program->program, ATTR_INDEX_NORMAL2, "attr_Normal2");
+
+#ifdef USE_VERT_TANGENT_SPACE
+ if(attribs & ATTR_TANGENT2)
+ qglBindAttribLocationARB(program->program, ATTR_INDEX_TANGENT2, "attr_Tangent2");
+
+ if(attribs & ATTR_BITANGENT2)
+ qglBindAttribLocationARB(program->program, ATTR_INDEX_BITANGENT2, "attr_Bitangent2");
+#endif
+
+ GLSL_LinkProgram(program->program);
+
+ program->numUniforms = numUniforms;
+
+ {
+ int i, size;
+
+ size = sizeof(*program->uniforms) * numUniforms;
+ program->uniforms = ri.Malloc(size);
+ for (i = 0; i < numUniforms; i++)
+ {
+ program->uniforms[i] = -1;
+ }
+
+ size = sizeof(*program->uniformTypes) * numUniforms;
+ program->uniformTypes = ri.Malloc(size);
+ memset(program->uniformTypes, 0, size);
+
+ size = sizeof(*program->uniformBufferOffsets) * numUniforms;
+ program->uniformBufferOffsets = ri.Malloc(size);
+ memset(program->uniformBufferOffsets, 0, size);
+ }
+
+ return 1;
+}
+
+static int GLSL_InitGPUShader(shaderProgram_t * program, const char *name,
+ int attribs, qboolean fragmentShader, const GLcharARB *extra, qboolean addHeader,
+ const char *fallback_vp, const char *fallback_fp, int numUniforms)
+{
+ char vpCode[32000];
+ char fpCode[32000];
+ char *postHeader;
+ int size;
+ int result;
+
+ size = sizeof(vpCode);
+ if (addHeader)
+ {
+ GLSL_GetShaderHeader(GL_VERTEX_SHADER_ARB, extra, vpCode, size);
+ postHeader = &vpCode[strlen(vpCode)];
+ size -= strlen(vpCode);
+ }
+ else
+ {
+ postHeader = &vpCode[0];
+ }
+
+ if (!GLSL_LoadGPUShaderText(name, fallback_vp, GL_VERTEX_SHADER_ARB, postHeader, size, qfalse))
+ {
+ return 0;
+ }
+
+ if (fragmentShader)
+ {
+ size = sizeof(fpCode);
+ if (addHeader)
+ {
+ GLSL_GetShaderHeader(GL_FRAGMENT_SHADER_ARB, extra, fpCode, size);
+ postHeader = &fpCode[strlen(fpCode)];
+ size -= strlen(fpCode);
+ }
+ else
+ {
+ postHeader = &fpCode[0];
+ }
+
+ if (!GLSL_LoadGPUShaderText(name, fallback_fp, GL_FRAGMENT_SHADER_ARB, postHeader, size, qfalse))
+ {
+ return 0;
+ }
+ }
+
+ result = GLSL_InitGPUShader2(program, name, attribs, vpCode, fragmentShader ? fpCode : NULL, numUniforms);
+
+ return result;
+}
+
+// intentionally deceiving the user here, not actually setting the names but getting their indexes.
+void GLSL_AddUniform(shaderProgram_t *program, int uniformNum, const char *name, int type)
+{
+ GLint *uniforms = program->uniforms;
+
+ uniforms[uniformNum] = qglGetUniformLocationARB(program->program, name);
+ program->uniformTypes[uniformNum] = type;
+}
+
+void GLSL_EndUniforms(shaderProgram_t *program)
+{
+ if (program->numUniforms)
+ {
+ int i, size;
+
+ size = 0;
+ for (i = 0; i < program->numUniforms; i++)
+ {
+ if (program->uniforms[i] != -1)
+ {
+ program->uniformBufferOffsets[i] = size;
+
+ switch(program->uniformTypes[i])
+ {
+ case GLSL_INT:
+ size += sizeof(GLint);
+ break;
+ case GLSL_FLOAT:
+ size += sizeof(GLfloat);
+ break;
+ case GLSL_FLOAT5:
+ size += sizeof(vec_t) * 5;
+ break;
+ case GLSL_VEC2:
+ size += sizeof(vec_t) * 2;
+ break;
+ case GLSL_VEC3:
+ size += sizeof(vec_t) * 3;
+ break;
+ case GLSL_VEC4:
+ size += sizeof(vec_t) * 4;
+ break;
+ case GLSL_MAT16:
+ size += sizeof(vec_t) * 16;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ program->uniformBuffer = ri.Malloc(size);
+
+ }
+}
+
+void GLSL_FinishGPUShader(shaderProgram_t *program)
+{
+ GLSL_ValidateProgram(program->program);
+ GLSL_ShowProgramUniforms(program->program);
+ GL_CheckErrors();
+}
+
+void GLSL_SetUniformInt(shaderProgram_t *program, int uniformNum, GLint value)
+{
+ GLint *uniforms = program->uniforms;
+ GLint *compare = (GLint *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]);
+
+ if (uniforms[uniformNum] == -1)
+ return;
+
+ if (program->uniformTypes[uniformNum] != GLSL_INT)
+ {
+ ri.Printf( PRINT_WARNING, "GLSL_SetUniformInt: wrong type for uniform %i in program %s\n", uniformNum, program->name);
+ return;
+ }
+
+ if (value == *compare)
+ {
+ return;
+ }
+
+ *compare = value;
+
+ qglUniform1iARB(uniforms[uniformNum], value);
+}
+
+void GLSL_SetUniformFloat(shaderProgram_t *program, int uniformNum, GLfloat value)
+{
+ GLint *uniforms = program->uniforms;
+ GLfloat *compare = (GLfloat *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]);
+
+ if (uniforms[uniformNum] == -1)
+ return;
+
+ if (program->uniformTypes[uniformNum] != GLSL_FLOAT)
+ {
+ ri.Printf( PRINT_WARNING, "GLSL_SetUniformFloat: wrong type for uniform %i in program %s\n", uniformNum, program->name);
+ return;
+ }
+
+ if (value == *compare)
+ {
+ return;
+ }
+
+ *compare = value;
+
+ qglUniform1fARB(uniforms[uniformNum], value);
+}
+
+void GLSL_SetUniformVec2(shaderProgram_t *program, int uniformNum, const vec2_t v)
+{
+ GLint *uniforms = program->uniforms;
+ vec_t *compare = (float *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]);
+
+ if (uniforms[uniformNum] == -1)
+ return;
+
+ if (program->uniformTypes[uniformNum] != GLSL_VEC2)
+ {
+ ri.Printf( PRINT_WARNING, "GLSL_SetUniformVec2: wrong type for uniform %i in program %s\n", uniformNum, program->name);
+ return;
+ }
+
+ if (v[0] == compare[0] && v[1] == compare[1])
+ {
+ return;
+ }
+
+ compare[0] = v[0];
+ compare[1] = v[1];
+
+ qglUniform2fARB(uniforms[uniformNum], v[0], v[1]);
+}
+
+void GLSL_SetUniformVec3(shaderProgram_t *program, int uniformNum, const vec3_t v)
+{
+ GLint *uniforms = program->uniforms;
+ vec_t *compare = (float *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]);
+
+ if (uniforms[uniformNum] == -1)
+ return;
+
+ if (program->uniformTypes[uniformNum] != GLSL_VEC3)
+ {
+ ri.Printf( PRINT_WARNING, "GLSL_SetUniformVec3: wrong type for uniform %i in program %s\n", uniformNum, program->name);
+ return;
+ }
+
+ if (VectorCompare(v, compare))
+ {
+ return;
+ }
+
+ VectorCopy(v, compare);
+
+ qglUniform3fARB(uniforms[uniformNum], v[0], v[1], v[2]);
+}
+
+void GLSL_SetUniformVec4(shaderProgram_t *program, int uniformNum, const vec4_t v)
+{
+ GLint *uniforms = program->uniforms;
+ vec_t *compare = (float *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]);
+
+ if (uniforms[uniformNum] == -1)
+ return;
+
+ if (program->uniformTypes[uniformNum] != GLSL_VEC4)
+ {
+ ri.Printf( PRINT_WARNING, "GLSL_SetUniformVec4: wrong type for uniform %i in program %s\n", uniformNum, program->name);
+ return;
+ }
+
+ if (VectorCompare4(v, compare))
+ {
+ return;
+ }
+
+ VectorCopy4(v, compare);
+
+ qglUniform4fARB(uniforms[uniformNum], v[0], v[1], v[2], v[3]);
+}
+
+void GLSL_SetUniformFloat5(shaderProgram_t *program, int uniformNum, const vec5_t v)
+{
+ GLint *uniforms = program->uniforms;
+ vec_t *compare = (float *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]);
+
+ if (uniforms[uniformNum] == -1)
+ {
+ ri.Printf( PRINT_ALL, "well shit.\n");
+ return;
+ }
+
+ if (program->uniformTypes[uniformNum] != GLSL_FLOAT5)
+ {
+ ri.Printf( PRINT_WARNING, "GLSL_SetUniformFloat5: wrong type for uniform %i in program %s\n", uniformNum, program->name);
+ return;
+ }
+
+ if (VectorCompare5(v, compare))
+ {
+ return;
+ }
+
+ VectorCopy5(v, compare);
+
+ qglUniform1fvARB(uniforms[uniformNum], 5, v);
+}
+
+void GLSL_SetUniformMatrix16(shaderProgram_t *program, int uniformNum, const matrix_t matrix)
+{
+ GLint *uniforms = program->uniforms;
+ vec_t *compare = (float *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]);
+
+ if (uniforms[uniformNum] == -1)
+ return;
+
+ if (program->uniformTypes[uniformNum] != GLSL_MAT16)
+ {
+ ri.Printf( PRINT_WARNING, "GLSL_SetUniformMatrix16: wrong type for uniform %i in program %s\n", uniformNum, program->name);
+ return;
+ }
+
+ if (Matrix16Compare(matrix, compare))
+ {
+ return;
+ }
+
+ Matrix16Copy(matrix, compare);
+
+ qglUniformMatrix4fvARB(uniforms[uniformNum], 1, GL_FALSE, matrix);
+}
+
+void GLSL_DeleteGPUShader(shaderProgram_t *program)
+{
+ if(program->program)
+ {
+ if (program->vertexShader)
+ {
+ qglDetachObjectARB(program->program, program->vertexShader);
+ qglDeleteObjectARB(program->vertexShader);
+ }
+
+ if (program->fragmentShader)
+ {
+ qglDetachObjectARB(program->program, program->fragmentShader);
+ qglDeleteObjectARB(program->fragmentShader);
+ }
+
+ qglDeleteObjectARB(program->program);
+
+ if (program->uniforms)
+ {
+ ri.Free(program->uniforms);
+ }
+
+ if (program->uniformTypes)
+ {
+ ri.Free(program->uniformTypes);
+ }
+
+ if (program->uniformBuffer)
+ {
+ ri.Free(program->uniformBuffer);
+ }
+
+ if (program->uniformBufferOffsets)
+ {
+ ri.Free(program->uniformBufferOffsets);
+ }
+
+ Com_Memset(program, 0, sizeof(*program));
+ }
+}
+
+void GLSL_InitGPUShaders(void)
+{
+ int startTime, endTime;
+ int i;
+ char extradefines[1024];
+ int attribs;
+ int numGenShaders = 0, numLightShaders = 0, numEtcShaders = 0;
+
+ ri.Printf(PRINT_ALL, "------- GLSL_InitGPUShaders -------\n");
+
+ // make sure the render thread is stopped
+ R_SyncRenderThread();
+
+ startTime = ri.Milliseconds();
+
+ for (i = 0; i < GENERICDEF_COUNT; i++)
+ {
+ attribs = ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_NORMAL | ATTR_COLOR;
+ extradefines[0] = '\0';
+
+ if (i & GENERICDEF_USE_DEFORM_VERTEXES)
+ Q_strcat(extradefines, 1024, "#define USE_DEFORM_VERTEXES\n");
+
+ if (i & GENERICDEF_USE_TCGEN)
+ Q_strcat(extradefines, 1024, "#define USE_TCGEN\n");
+
+ if (i & GENERICDEF_USE_VERTEX_ANIMATION)
+ {
+ Q_strcat(extradefines, 1024, "#define USE_VERTEX_ANIMATION\n");
+ attribs |= ATTR_POSITION2 | ATTR_NORMAL2;
+ }
+
+ if (i & GENERICDEF_USE_FOG)
+ Q_strcat(extradefines, 1024, "#define USE_FOG\n");
+
+ if (i & GENERICDEF_USE_RGBAGEN)
+ Q_strcat(extradefines, 1024, "#define USE_RGBAGEN\n");
+
+ if (i & GENERICDEF_USE_LIGHTMAP)
+ Q_strcat(extradefines, 1024, "#define USE_LIGHTMAP\n");
+
+ if (r_hdr->integer && !(glRefConfig.textureFloat && glRefConfig.halfFloatPixel))
+ Q_strcat(extradefines, 1024, "#define RGBE_LIGHTMAP\n");
+
+ if (!GLSL_InitGPUShader(&tr.genericShader[i], "generic", attribs, qtrue, extradefines, qtrue, fallbackGenericShader_vp, fallbackGenericShader_fp, GENERIC_UNIFORM_COUNT))
+ {
+ ri.Error(ERR_FATAL, "Could not load generic shader!\n");
+ }
+
+ // There's actually no need to filter these out, since they'll
+ // redirect to -1 if nonexistent, but it's more understandable this way.
+
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
+
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_BASECOLOR, "u_BaseColor", GLSL_VEC4);
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_VERTCOLOR, "u_VertColor", GLSL_VEC4);
+
+ if (i & GENERICDEF_USE_RGBAGEN)
+ {
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_COLORGEN, "u_ColorGen", GLSL_INT);
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_ALPHAGEN, "u_AlphaGen", GLSL_INT);
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_AMBIENTLIGHT, "u_AmbientLight", GLSL_VEC3);
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_DIRECTEDLIGHT, "u_DirectedLight", GLSL_VEC3);
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_LIGHTORIGIN, "u_LightOrigin", GLSL_VEC4);
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_PORTALRANGE, "u_PortalRange", GLSL_FLOAT);
+ }
+
+ if (i & GENERICDEF_USE_TCGEN)
+ {
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_TCGEN0, "u_TCGen0", GLSL_INT);
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_TCGEN0VECTOR0, "u_TCGen0Vector0", GLSL_VEC3);
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_TCGEN0VECTOR1, "u_TCGen0Vector1", GLSL_VEC3);
+ }
+
+ if (i & GENERICDEF_USE_FOG)
+ {
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_FOGCOLORMASK, "u_FogColorMask", GLSL_VEC4);
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_FOGDISTANCE, "u_FogDistance", GLSL_VEC4);
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_FOGDEPTH, "u_FogDepth", GLSL_VEC4);
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_FOGEYET, "u_FogEyeT", GLSL_FLOAT);
+ }
+
+ if (i & GENERICDEF_USE_DEFORM_VERTEXES)
+ {
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_DEFORMGEN, "u_DeformGen", GLSL_INT);
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_DEFORMPARAMS, "u_DeformParams", GLSL_FLOAT5);
+ }
+
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_TIME, "u_Time", GLSL_FLOAT);
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_VIEWORIGIN, "u_ViewOrigin", GLSL_VEC3);
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_DIFFUSETEXMATRIX, "u_DiffuseTexMatrix", GLSL_MAT16);
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_TEXTURE1ENV, "u_Texture1Env", GLSL_INT);
+
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_DIFFUSEMAP, "u_DiffuseMap", GLSL_INT);
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_LIGHTMAP, "u_LightMap", GLSL_INT);
+
+
+ if (i & GENERICDEF_USE_VERTEX_ANIMATION)
+ {
+ GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_VERTEXLERP, "u_VertexLerp", GLSL_FLOAT);
+ }
+
+ GLSL_EndUniforms(&tr.genericShader[i]);
+
+ qglUseProgramObjectARB(tr.genericShader[i].program);
+ GLSL_SetUniformInt(&tr.genericShader[i], GENERIC_UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP);
+ GLSL_SetUniformInt(&tr.genericShader[i], GENERIC_UNIFORM_LIGHTMAP, TB_LIGHTMAP);
+ qglUseProgramObjectARB(0);
+
+ GLSL_FinishGPUShader(&tr.genericShader[i]);
+
+ numGenShaders++;
+ }
+
+
+ attribs = ATTR_POSITION | ATTR_TEXCOORD;
+
+ if (!GLSL_InitGPUShader(&tr.textureColorShader, "texturecolor", attribs, qtrue, NULL, qfalse, fallbackTextureColorShader_vp, fallbackTextureColorShader_fp, TEXTURECOLOR_UNIFORM_COUNT))
+ {
+ ri.Error(ERR_FATAL, "Could not load texturecolor shader!\n");
+ }
+
+ GLSL_AddUniform(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
+ GLSL_AddUniform(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_COLOR, "u_Color", GLSL_VEC4);
+ GLSL_AddUniform(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, "u_DiffuseMap", GLSL_INT);
+
+ GLSL_EndUniforms(&tr.textureColorShader);
+
+ qglUseProgramObjectARB(tr.textureColorShader.program);
+ GLSL_SetUniformInt(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP);
+ qglUseProgramObjectARB(0);
+
+ GLSL_FinishGPUShader(&tr.textureColorShader);
+
+ numEtcShaders++;
+
+
+ attribs = ATTR_POSITION | ATTR_POSITION2 | ATTR_NORMAL | ATTR_NORMAL2 | ATTR_TEXCOORD;
+
+ if (!GLSL_InitGPUShader(&tr.fogShader, "fogpass", attribs, qtrue, NULL, qtrue, fallbackFogPassShader_vp, fallbackFogPassShader_fp, FOGPASS_UNIFORM_COUNT))
+ {
+ ri.Error(ERR_FATAL, "Could not load fogpass shader!\n");
+ }
+
+ GLSL_AddUniform(&tr.fogShader, FOGPASS_UNIFORM_FOGDISTANCE, "u_FogDistance", GLSL_VEC4);
+ GLSL_AddUniform(&tr.fogShader, FOGPASS_UNIFORM_FOGDEPTH, "u_FogDepth", GLSL_VEC4);
+ GLSL_AddUniform(&tr.fogShader, FOGPASS_UNIFORM_FOGEYET, "u_FogEyeT", GLSL_FLOAT);
+ GLSL_AddUniform(&tr.fogShader, FOGPASS_UNIFORM_DEFORMGEN, "u_DeformGen", GLSL_INT);
+ GLSL_AddUniform(&tr.fogShader, FOGPASS_UNIFORM_DEFORMPARAMS, "u_DeformParams", GLSL_FLOAT5);
+ GLSL_AddUniform(&tr.fogShader, FOGPASS_UNIFORM_TIME, "u_Time", GLSL_FLOAT);
+ GLSL_AddUniform(&tr.fogShader, FOGPASS_UNIFORM_COLOR, "u_Color", GLSL_VEC4);
+ GLSL_AddUniform(&tr.fogShader, FOGPASS_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
+ GLSL_AddUniform(&tr.fogShader, FOGPASS_UNIFORM_VERTEXLERP, "u_VertexLerp", GLSL_FLOAT);
+
+ GLSL_EndUniforms(&tr.fogShader);
+ GLSL_FinishGPUShader(&tr.fogShader);
+
+ numEtcShaders++;
+
+
+ attribs = ATTR_POSITION | ATTR_NORMAL | ATTR_TEXCOORD;
+
+ if (!GLSL_InitGPUShader(&tr.dlightallShader, "dlight", attribs, qtrue, NULL, qtrue, fallbackDlightShader_vp, fallbackDlightShader_fp, DLIGHT_UNIFORM_COUNT))
+ {
+ ri.Error(ERR_FATAL, "Could not load dlight shader!\n");
+ }
+
+ GLSL_AddUniform(&tr.dlightallShader, DLIGHT_UNIFORM_DLIGHTINFO, "u_DlightInfo", GLSL_VEC4);
+ GLSL_AddUniform(&tr.dlightallShader, DLIGHT_UNIFORM_DEFORMGEN, "u_DeformGen", GLSL_INT);
+ GLSL_AddUniform(&tr.dlightallShader, DLIGHT_UNIFORM_DEFORMPARAMS, "u_DeformParams", GLSL_FLOAT5);
+ GLSL_AddUniform(&tr.dlightallShader, DLIGHT_UNIFORM_TIME, "u_Time", GLSL_FLOAT);
+ GLSL_AddUniform(&tr.dlightallShader, DLIGHT_UNIFORM_COLOR, "u_Color", GLSL_VEC4);
+ GLSL_AddUniform(&tr.dlightallShader, DLIGHT_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
+
+ GLSL_EndUniforms(&tr.dlightallShader);
+
+ qglUseProgramObjectARB(tr.dlightallShader.program);
+ GLSL_SetUniformInt(&tr.dlightallShader, DLIGHT_UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP);
+ qglUseProgramObjectARB(0);
+
+ GLSL_FinishGPUShader(&tr.dlightallShader);
+
+ numEtcShaders++;
+
+
+ for (i = 0; i < LIGHTDEF_COUNT; i++)
+ {
+ // skip impossible combos
+ if ((i & LIGHTDEF_USE_NORMALMAP) && !r_normalMapping->integer)
+ continue;
+
+ if ((i & LIGHTDEF_USE_PARALLAXMAP) && !r_parallaxMapping->integer)
+ continue;
+
+ if ((i & LIGHTDEF_USE_SPECULARMAP) && !r_specularMapping->integer)
+ continue;
+
+ if ((i & LIGHTDEF_USE_DELUXEMAP) && !r_deluxeMapping->integer)
+ continue;
+
+ if (!((i & LIGHTDEF_LIGHTTYPE_MASK) == LIGHTDEF_USE_LIGHTMAP) && (i & LIGHTDEF_USE_DELUXEMAP))
+ continue;
+
+ if (!(i & LIGHTDEF_USE_NORMALMAP) && (i & LIGHTDEF_USE_PARALLAXMAP))
+ continue;
+
+ if (!((i & LIGHTDEF_LIGHTTYPE_MASK) == LIGHTDEF_USE_LIGHT_VECTOR))
+ {
+ if (i & LIGHTDEF_USE_SHADOWMAP)
+ continue;
+ }
+
+ attribs = ATTR_POSITION | ATTR_TEXCOORD | ATTR_COLOR | ATTR_NORMAL;
+
+ extradefines[0] = '\0';
+
+ if (r_normalAmbient->value > 0.003f)
+ Q_strcat(extradefines, 1024, va("#define r_normalAmbient %f\n", r_normalAmbient->value));
+
+ if (r_dlightMode->integer >= 2)
+ Q_strcat(extradefines, 1024, "#define USE_SHADOWMAP\n");
+
+ if (1)
+ {
+ Q_strcat(extradefines, 1024, "#define SWIZZLE_NORMALMAP\n");
+ }
+
+ if (r_hdr->integer && !(glRefConfig.textureFloat && glRefConfig.halfFloatPixel))
+ Q_strcat(extradefines, 1024, "#define RGBE_LIGHTMAP\n");
+
+ if (i & LIGHTDEF_LIGHTTYPE_MASK)
+ {
+ Q_strcat(extradefines, 1024, "#define USE_LIGHT\n");
+
+ if (r_normalMapping->integer == 0 && r_specularMapping->integer == 0)
+ Q_strcat(extradefines, 1024, "#define USE_FAST_LIGHT\n");
+
+ switch (i & LIGHTDEF_LIGHTTYPE_MASK)
+ {
+ case LIGHTDEF_USE_LIGHTMAP:
+ Q_strcat(extradefines, 1024, "#define USE_LIGHTMAP\n");
+ attribs |= ATTR_LIGHTCOORD | ATTR_LIGHTDIRECTION;
+ break;
+ case LIGHTDEF_USE_LIGHT_VECTOR:
+ Q_strcat(extradefines, 1024, "#define USE_LIGHT_VECTOR\n");
+ break;
+ case LIGHTDEF_USE_LIGHT_VERTEX:
+ Q_strcat(extradefines, 1024, "#define USE_LIGHT_VERTEX\n");
+ attribs |= ATTR_LIGHTDIRECTION;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if ((i & LIGHTDEF_USE_NORMALMAP) && r_normalMapping->integer)
+ {
+ Q_strcat(extradefines, 1024, "#define USE_NORMALMAP\n");
+
+ if (r_normalMapping->integer == 2)
+ Q_strcat(extradefines, 1024, "#define USE_OREN_NAYAR\n");
+
+ if (r_normalMapping->integer == 3)
+ Q_strcat(extradefines, 1024, "#define USE_TRIACE_OREN_NAYAR\n");
+
+#ifdef USE_VERT_TANGENT_SPACE
+ Q_strcat(extradefines, 1024, "#define USE_VERT_TANGENT_SPACE\n");
+ attribs |= ATTR_TANGENT | ATTR_BITANGENT;
+#endif
+ }
+
+ if ((i & LIGHTDEF_USE_SPECULARMAP) && r_specularMapping->integer)
+ {
+ Q_strcat(extradefines, 1024, "#define USE_SPECULARMAP\n");
+
+ switch (r_specularMapping->integer)
+ {
+ case 1:
+ default:
+ Q_strcat(extradefines, 1024, "#define USE_TRIACE\n");
+ break;
+
+ case 2:
+ Q_strcat(extradefines, 1024, "#define USE_BLINN\n");
+ break;
+
+ case 3:
+ Q_strcat(extradefines, 1024, "#define USE_COOK_TORRANCE\n");
+ break;
+
+ case 4:
+ Q_strcat(extradefines, 1024, "#define USE_TORRANCE_SPARROW\n");
+ break;
+ }
+ }
+
+ if ((i & LIGHTDEF_USE_DELUXEMAP) && r_deluxeMapping->integer)
+ Q_strcat(extradefines, 1024, "#define USE_DELUXEMAP\n");
+
+ if ((i & LIGHTDEF_USE_PARALLAXMAP) && !(i & LIGHTDEF_ENTITY) && r_parallaxMapping->integer)
+ Q_strcat(extradefines, 1024, "#define USE_PARALLAXMAP\n");
+
+ if (i & LIGHTDEF_USE_SHADOWMAP)
+ Q_strcat(extradefines, 1024, "#define USE_SHADOWMAP\n");
+
+ if (i & LIGHTDEF_TCGEN_ENVIRONMENT)
+ Q_strcat(extradefines, 1024, "#define TCGEN_ENVIRONMENT\n");
+
+ if (i & LIGHTDEF_ENTITY)
+ {
+ Q_strcat(extradefines, 1024, "#define USE_VERTEX_ANIMATION\n#define USE_MODELMATRIX\n");
+ attribs |= ATTR_POSITION2 | ATTR_NORMAL2;
+
+#ifdef USE_VERT_TANGENT_SPACE
+ if (i & LIGHTDEF_USE_NORMALMAP && r_normalMapping->integer)
+ {
+ attribs |= ATTR_TANGENT2 | ATTR_BITANGENT2;
+ }
+#endif
+ }
+
+ if (!GLSL_InitGPUShader(&tr.lightallShader[i], "lightall", attribs, qtrue, extradefines, qtrue, fallbackLightallShader_vp, fallbackLightallShader_fp, GENERIC_UNIFORM_COUNT))
+ {
+ ri.Error(ERR_FATAL, "Could not load lightall shader!\n");
+ }
+
+ GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
+ GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_MODELMATRIX, "u_ModelMatrix", GLSL_MAT16);
+ GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_DIFFUSETEXMATRIX, "u_DiffuseTexMatrix", GLSL_MAT16);
+ //GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_NORMALTEXMATRIX, "u_NormalTexMatrix", GLSL_MAT16);
+ //GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_SPECULARTEXMATRIX, "u_SpecularTexMatrix", GLSL_MAT16);
+ GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_VIEWORIGIN, "u_ViewOrigin", GLSL_VEC3);
+
+ GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_DIFFUSEMAP, "u_DiffuseMap", GLSL_INT);
+ GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_LIGHTMAP, "u_LightMap", GLSL_INT);
+ GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_NORMALMAP, "u_NormalMap", GLSL_INT);
+ GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_DELUXEMAP, "u_DeluxeMap", GLSL_INT);
+ GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_SPECULARMAP, "u_SpecularMap", GLSL_INT);
+ GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_SHADOWMAP, "u_ShadowMap", GLSL_INT);
+
+ GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_AMBIENTLIGHT, "u_AmbientLight", GLSL_VEC3);
+ GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_DIRECTEDLIGHT, "u_DirectedLight", GLSL_VEC3);
+ GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_LIGHTORIGIN, "u_LightOrigin", GLSL_VEC4);
+ GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_LIGHTRADIUS, "u_LightRadius", GLSL_FLOAT);
+
+ GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_MATERIALINFO, "u_MaterialInfo", GLSL_VEC2);
+
+ GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_BASECOLOR, "u_BaseColor", GLSL_VEC4);
+ GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_VERTCOLOR, "u_VertColor", GLSL_VEC4);
+ GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_VERTEXLERP, "u_VertexLerp", GLSL_FLOAT);
+
+ GLSL_EndUniforms(&tr.lightallShader[i]);
+
+ qglUseProgramObjectARB(tr.lightallShader[i].program);
+ GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP);
+ GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_LIGHTMAP, TB_LIGHTMAP);
+ GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_NORMALMAP, TB_NORMALMAP);
+ GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_DELUXEMAP, TB_DELUXEMAP);
+ GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_SPECULARMAP, TB_SPECULARMAP);
+ GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_SHADOWMAP, TB_SHADOWMAP);
+ qglUseProgramObjectARB(0);
+
+ GLSL_FinishGPUShader(&tr.lightallShader[i]);
+
+ numLightShaders++;
+ }
+
+ attribs = ATTR_POSITION | ATTR_POSITION2 | ATTR_NORMAL | ATTR_NORMAL2 | ATTR_TEXCOORD;
+
+ extradefines[0] = '\0';
+
+ if (!GLSL_InitGPUShader(&tr.shadowmapShader, "shadowfill", attribs, qtrue, extradefines, qtrue, fallbackShadowfillShader_vp, fallbackShadowfillShader_fp, GENERIC_UNIFORM_COUNT))
+ {
+ ri.Error(ERR_FATAL, "Could not load shadowfill shader!\n");
+ }
+
+ GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_DEFORMGEN, "u_DeformGen", GLSL_INT);
+ GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_DEFORMPARAMS, "u_DeformParams", GLSL_FLOAT5);
+ GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_TIME, "u_Time", GLSL_FLOAT);
+ GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
+ GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_MODELMATRIX, "u_ModelMatrix", GLSL_MAT16);
+ GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_VERTEXLERP, "u_VertexLerp", GLSL_FLOAT);
+
+ GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_LIGHTORIGIN, "u_LightOrigin", GLSL_VEC4);
+ GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_LIGHTRADIUS, "u_LightRadius", GLSL_FLOAT);
+
+ GLSL_EndUniforms(&tr.shadowmapShader);
+ GLSL_FinishGPUShader(&tr.shadowmapShader);
+
+ numEtcShaders++;
+
+ attribs = ATTR_POSITION | ATTR_NORMAL;
+ extradefines[0] = '\0';
+
+ Q_strcat(extradefines, 1024, "#define USE_PCF\n#define USE_DISCARD\n");
+
+ if (!GLSL_InitGPUShader(&tr.pshadowShader, "pshadow", attribs, qtrue, extradefines, qtrue, fallbackPshadowShader_vp, fallbackPshadowShader_fp, PSHADOW_UNIFORM_COUNT))
+ {
+ ri.Error(ERR_FATAL, "Could not load pshadow shader!\n");
+ }
+
+ GLSL_AddUniform(&tr.pshadowShader, PSHADOW_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
+ GLSL_AddUniform(&tr.pshadowShader, PSHADOW_UNIFORM_LIGHTFORWARD, "u_LightForward", GLSL_VEC3);
+ GLSL_AddUniform(&tr.pshadowShader, PSHADOW_UNIFORM_LIGHTUP, "u_LightUp", GLSL_VEC3);
+ GLSL_AddUniform(&tr.pshadowShader, PSHADOW_UNIFORM_LIGHTRIGHT, "u_LightRight", GLSL_VEC3);
+ GLSL_AddUniform(&tr.pshadowShader, PSHADOW_UNIFORM_LIGHTORIGIN, "u_LightOrigin", GLSL_VEC4);
+ GLSL_AddUniform(&tr.pshadowShader, PSHADOW_UNIFORM_LIGHTRADIUS, "u_LightRadius", GLSL_FLOAT);
+
+ GLSL_EndUniforms(&tr.pshadowShader);
+
+ qglUseProgramObjectARB(tr.pshadowShader.program);
+ GLSL_SetUniformInt(&tr.pshadowShader, PSHADOW_UNIFORM_SHADOWMAP, TB_DIFFUSEMAP);
+ qglUseProgramObjectARB(0);
+
+ GLSL_FinishGPUShader(&tr.pshadowShader);
+
+ numEtcShaders++;
+
+
+ attribs = ATTR_POSITION | ATTR_TEXCOORD;
+ extradefines[0] = '\0';
+
+ if (!GLSL_InitGPUShader(&tr.down4xShader, "down4x", attribs, qtrue, extradefines, qtrue, fallbackDown4xShader_vp, fallbackDown4xShader_fp, TEXTURECOLOR_UNIFORM_COUNT))
+ {
+ ri.Error(ERR_FATAL, "Could not load down4x shader!\n");
+ }
+
+ GLSL_AddUniform(&tr.down4xShader, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
+ GLSL_AddUniform(&tr.down4xShader, TEXTURECOLOR_UNIFORM_INVTEXRES, "u_InvTexRes", GLSL_VEC2);
+
+ GLSL_AddUniform(&tr.down4xShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, "u_TextureMap", GLSL_INT);
+
+ GLSL_EndUniforms(&tr.down4xShader);
+
+ qglUseProgramObjectARB(tr.down4xShader.program);
+ GLSL_SetUniformInt(&tr.down4xShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP);
+ qglUseProgramObjectARB(0);
+
+ GLSL_FinishGPUShader(&tr.down4xShader);
+
+ numEtcShaders++;
+
+
+ attribs = ATTR_POSITION | ATTR_TEXCOORD;
+ extradefines[0] = '\0';
+
+ if (!GLSL_InitGPUShader(&tr.bokehShader, "bokeh", attribs, qtrue, extradefines, qtrue, fallbackBokehShader_vp, fallbackBokehShader_fp, TEXTURECOLOR_UNIFORM_COUNT))
+ {
+ ri.Error(ERR_FATAL, "Could not load bokeh shader!\n");
+ }
+
+ GLSL_AddUniform(&tr.bokehShader, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
+ GLSL_AddUniform(&tr.bokehShader, TEXTURECOLOR_UNIFORM_INVTEXRES, "u_InvTexRes", GLSL_VEC2);
+ GLSL_AddUniform(&tr.bokehShader, TEXTURECOLOR_UNIFORM_COLOR, "u_Color", GLSL_VEC4);
+
+ GLSL_AddUniform(&tr.bokehShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, "u_TextureMap", GLSL_INT);
+
+ GLSL_EndUniforms(&tr.bokehShader);
+
+ qglUseProgramObjectARB(tr.bokehShader.program);
+ GLSL_SetUniformInt(&tr.bokehShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP);
+ qglUseProgramObjectARB(0);
+
+ GLSL_FinishGPUShader(&tr.bokehShader);
+
+ numEtcShaders++;
+
+
+ attribs = ATTR_POSITION | ATTR_TEXCOORD;
+ extradefines[0] = '\0';
+
+ if (!GLSL_InitGPUShader(&tr.tonemapShader, "tonemap", attribs, qtrue, extradefines, qtrue, fallbackToneMapShader_vp, fallbackToneMapShader_fp, TEXTURECOLOR_UNIFORM_COUNT))
+ {
+ ri.Error(ERR_FATAL, "Could not load tonemap shader!\n");
+ }
+
+ GLSL_AddUniform(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
+ GLSL_AddUniform(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_INVTEXRES, "u_InvTexRes", GLSL_VEC2);
+ GLSL_AddUniform(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_COLOR, "u_Color", GLSL_VEC4);
+ GLSL_AddUniform(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_AUTOEXPOSUREMINMAX, "u_AutoExposureMinMax", GLSL_VEC2);
+ GLSL_AddUniform(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_TONEMINAVGMAXLINEAR, "u_ToneMinAvgMaxLinear", GLSL_VEC3);
+ GLSL_AddUniform(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, "u_TextureMap", GLSL_INT);
+ GLSL_AddUniform(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_LEVELSMAP, "u_LevelsMap", GLSL_INT);
+
+ GLSL_EndUniforms(&tr.tonemapShader);
+
+ qglUseProgramObjectARB(tr.tonemapShader.program);
+ GLSL_SetUniformInt(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, TB_COLORMAP);
+ GLSL_SetUniformInt(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_LEVELSMAP, TB_LEVELSMAP);
+ qglUseProgramObjectARB(0);
+
+ GLSL_FinishGPUShader(&tr.tonemapShader);
+
+ numEtcShaders++;
+
+
+ for (i = 0; i < 2; i++)
+ {
+ attribs = ATTR_POSITION | ATTR_TEXCOORD;
+ extradefines[0] = '\0';
+
+ if (!i)
+ Q_strcat(extradefines, 1024, "#define FIRST_PASS\n");
+
+ if (!GLSL_InitGPUShader(&tr.calclevels4xShader[i], "calclevels4x", attribs, qtrue, extradefines, qtrue, fallbackCalcLevels4xShader_vp, fallbackCalcLevels4xShader_fp, TEXTURECOLOR_UNIFORM_COUNT))
+ {
+ ri.Error(ERR_FATAL, "Could not load calclevels4x shader!\n");
+ }
+
+ GLSL_AddUniform(&tr.calclevels4xShader[i], TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
+ GLSL_AddUniform(&tr.calclevels4xShader[i], TEXTURECOLOR_UNIFORM_INVTEXRES, "u_InvTexRes", GLSL_VEC2);
+ GLSL_AddUniform(&tr.calclevels4xShader[i], TEXTURECOLOR_UNIFORM_COLOR, "u_Color", GLSL_VEC4);
+
+ GLSL_AddUniform(&tr.calclevels4xShader[i], TEXTURECOLOR_UNIFORM_TEXTUREMAP, "u_TextureMap", GLSL_INT);
+
+ GLSL_EndUniforms(&tr.calclevels4xShader[i]);
+
+ qglUseProgramObjectARB(tr.calclevels4xShader[i].program);
+ GLSL_SetUniformInt(&tr.calclevels4xShader[i], TEXTURECOLOR_UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP);
+ qglUseProgramObjectARB(0);
+
+ GLSL_FinishGPUShader(&tr.calclevels4xShader[i]);
+
+ numEtcShaders++;
+ }
+
+
+ attribs = ATTR_POSITION | ATTR_TEXCOORD;
+ extradefines[0] = '\0';
+
+ if (r_shadowFilter->integer >= 1)
+ Q_strcat(extradefines, 1024, "#define USE_SHADOW_FILTER\n");
+
+ if (r_shadowFilter->integer >= 2)
+ Q_strcat(extradefines, 1024, "#define USE_SHADOW_FILTER2\n");
+
+ Q_strcat(extradefines, 1024, "#define USE_SHADOW_CASCADE\n");
+
+ Q_strcat(extradefines, 1024, va("#define r_shadowMapSize %d\n", r_shadowMapSize->integer));
+ Q_strcat(extradefines, 1024, va("#define r_shadowCascadeZFar %f\n", r_shadowCascadeZFar->value));
+
+
+ if (!GLSL_InitGPUShader(&tr.shadowmaskShader, "shadowmask", attribs, qtrue, extradefines, qtrue, fallbackShadowmaskShader_vp, fallbackShadowmaskShader_fp, SHADOWMASK_UNIFORM_COUNT))
+ {
+ ri.Error(ERR_FATAL, "Could not load shadowmask shader!\n");
+ }
+
+ GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMVP, "u_ShadowMvp", GLSL_MAT16);
+ GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMVP2, "u_ShadowMvp2", GLSL_MAT16);
+ GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMVP3, "u_ShadowMvp3", GLSL_MAT16);
+ GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWORIGIN, "u_ViewOrigin", GLSL_VEC3);
+ GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWINFO, "u_ViewInfo", GLSL_VEC4);
+ GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWFORWARD,"u_ViewForward", GLSL_VEC3);
+ GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWLEFT, "u_ViewLeft", GLSL_VEC3);
+ GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWUP, "u_ViewUp", GLSL_VEC3);
+
+ GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SCREENDEPTHMAP, "u_ScreenDepthMap", GLSL_INT);
+ GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMAP, "u_ShadowMap", GLSL_INT);
+ GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMAP2, "u_ShadowMap2", GLSL_INT);
+ GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMAP3, "u_ShadowMap3", GLSL_INT);
+
+ GLSL_EndUniforms(&tr.shadowmaskShader);
+
+ qglUseProgramObjectARB(tr.shadowmaskShader.program);
+ GLSL_SetUniformInt(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SCREENDEPTHMAP, TB_COLORMAP);
+ GLSL_SetUniformInt(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMAP, TB_SHADOWMAP);
+ GLSL_SetUniformInt(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMAP2, TB_SHADOWMAP2);
+ GLSL_SetUniformInt(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMAP3, TB_SHADOWMAP3);
+ qglUseProgramObjectARB(0);
+
+ GLSL_FinishGPUShader(&tr.shadowmaskShader);
+
+ numEtcShaders++;
+
+
+ attribs = ATTR_POSITION | ATTR_TEXCOORD;
+ extradefines[0] = '\0';
+
+ if (!GLSL_InitGPUShader(&tr.ssaoShader, "ssao", attribs, qtrue, extradefines, qtrue, fallbackSsaoShader_vp, fallbackSsaoShader_fp, SSAO_UNIFORM_COUNT))
+ {
+ ri.Error(ERR_FATAL, "Could not load ssao shader!\n");
+ }
+
+ GLSL_AddUniform(&tr.ssaoShader, SSAO_UNIFORM_VIEWINFO, "u_ViewInfo", GLSL_VEC4);
+
+ GLSL_AddUniform(&tr.ssaoShader, SSAO_UNIFORM_SCREENDEPTHMAP, "u_ScreenDepthMap", GLSL_INT);
+
+ GLSL_EndUniforms(&tr.ssaoShader);
+
+ qglUseProgramObjectARB(tr.ssaoShader.program);
+ GLSL_SetUniformInt(&tr.ssaoShader, SSAO_UNIFORM_SCREENDEPTHMAP, TB_COLORMAP);
+ qglUseProgramObjectARB(0);
+
+ GLSL_FinishGPUShader(&tr.ssaoShader);
+
+ numEtcShaders++;
+
+
+ for (i = 0; i < 2; i++)
+ {
+ attribs = ATTR_POSITION | ATTR_TEXCOORD;
+ extradefines[0] = '\0';
+
+ if (i & 1)
+ Q_strcat(extradefines, 1024, "#define USE_VERTICAL_BLUR\n");
+ else
+ Q_strcat(extradefines, 1024, "#define USE_HORIZONTAL_BLUR\n");
+
+
+ if (!GLSL_InitGPUShader(&tr.depthBlurShader[i], "depthBlur", attribs, qtrue, extradefines, qtrue, fallbackDepthBlurShader_vp, fallbackDepthBlurShader_fp, DEPTHBLUR_UNIFORM_COUNT))
+ {
+ ri.Error(ERR_FATAL, "Could not load depthBlur shader!\n");
+ }
+
+ GLSL_AddUniform(&tr.depthBlurShader[i], DEPTHBLUR_UNIFORM_VIEWINFO, "u_ViewInfo", GLSL_VEC4);
+
+ GLSL_AddUniform(&tr.depthBlurShader[i], DEPTHBLUR_UNIFORM_SCREENIMAGEMAP, "u_ScreenImageMap", GLSL_INT);
+ GLSL_AddUniform(&tr.depthBlurShader[i], DEPTHBLUR_UNIFORM_SCREENDEPTHMAP, "u_ScreenDepthMap", GLSL_INT);
+
+ GLSL_EndUniforms(&tr.depthBlurShader[i]);
+
+ qglUseProgramObjectARB(tr.depthBlurShader[i].program);
+ GLSL_SetUniformInt(&tr.depthBlurShader[i], DEPTHBLUR_UNIFORM_SCREENIMAGEMAP, TB_COLORMAP);
+ GLSL_SetUniformInt(&tr.depthBlurShader[i], DEPTHBLUR_UNIFORM_SCREENDEPTHMAP, TB_LIGHTMAP);
+ qglUseProgramObjectARB(0);
+
+ GLSL_FinishGPUShader(&tr.depthBlurShader[i]);
+
+ numEtcShaders++;
+ }
+
+
+ endTime = ri.Milliseconds();
+
+ ri.Printf(PRINT_ALL, "loaded %i GLSL shaders (%i gen %i light %i etc) in %5.2f seconds\n",
+ numGenShaders + numLightShaders + numEtcShaders, numGenShaders, numLightShaders,
+ numEtcShaders, (endTime - startTime) / 1000.0);
+
+ if (0)
+ {
+ GLSL_LoadGPUShaderText("Generic", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue);
+ GLSL_LoadGPUShaderText("Generic", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue);
+
+ GLSL_LoadGPUShaderText("TextureColor", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue);
+ GLSL_LoadGPUShaderText("TextureColor", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue);
+
+ GLSL_LoadGPUShaderText("FogPass", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue);
+ GLSL_LoadGPUShaderText("FogPass", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue);
+
+ GLSL_LoadGPUShaderText("Dlight", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue);
+ GLSL_LoadGPUShaderText("Dlight", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue);
+
+ GLSL_LoadGPUShaderText("Lightall", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue);
+ GLSL_LoadGPUShaderText("Lightall", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue);
+
+ GLSL_LoadGPUShaderText("Shadowfill", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue);
+ GLSL_LoadGPUShaderText("Shadowfill", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue);
+
+ GLSL_LoadGPUShaderText("Pshadow", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue);
+ GLSL_LoadGPUShaderText("Pshadow", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue);
+
+ GLSL_LoadGPUShaderText("Down4x", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue);
+ GLSL_LoadGPUShaderText("Down4x", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue);
+
+ GLSL_LoadGPUShaderText("Bokeh", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue);
+ GLSL_LoadGPUShaderText("Bokeh", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue);
+
+ GLSL_LoadGPUShaderText("ToneMap", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue);
+ GLSL_LoadGPUShaderText("ToneMap", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue);
+
+ GLSL_LoadGPUShaderText("CalcLevels4x", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue);
+ GLSL_LoadGPUShaderText("CalcLevels4x", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue);
+
+ GLSL_LoadGPUShaderText("Shadowmask", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue);
+ GLSL_LoadGPUShaderText("Shadowmask", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue);
+
+ GLSL_LoadGPUShaderText("Ssao", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue);
+ GLSL_LoadGPUShaderText("Ssao", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue);
+
+ GLSL_LoadGPUShaderText("DepthBlur", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue);
+ GLSL_LoadGPUShaderText("DepthBlur", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue);
+ }
+
+}
+
+void GLSL_ShutdownGPUShaders(void)
+{
+ int i;
+
+ ri.Printf(PRINT_ALL, "------- GLSL_ShutdownGPUShaders -------\n");
+
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD0);
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD1);
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_POSITION);
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_POSITION2);
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_NORMAL);
+#ifdef USE_VERT_TANGENT_SPACE
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT);
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_BITANGENT);
+#endif
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_NORMAL2);
+#ifdef USE_VERT_TANGENT_SPACE
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT2);
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_BITANGENT2);
+#endif
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_COLOR);
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_LIGHTDIRECTION);
+ GLSL_BindNullProgram();
+
+ for ( i = 0; i < GENERICDEF_COUNT; i++)
+ GLSL_DeleteGPUShader(&tr.genericShader[i]);
+
+ GLSL_DeleteGPUShader(&tr.textureColorShader);
+ GLSL_DeleteGPUShader(&tr.fogShader);
+ GLSL_DeleteGPUShader(&tr.dlightallShader);
+
+ for ( i = 0; i < LIGHTDEF_COUNT; i++)
+ GLSL_DeleteGPUShader(&tr.lightallShader[i]);
+
+ GLSL_DeleteGPUShader(&tr.shadowmapShader);
+ GLSL_DeleteGPUShader(&tr.pshadowShader);
+ GLSL_DeleteGPUShader(&tr.down4xShader);
+
+ for ( i = 0; i < 2; i++)
+ GLSL_DeleteGPUShader(&tr.calclevels4xShader[i]);
+
+ glState.currentProgram = 0;
+ qglUseProgramObjectARB(0);
+}
+
+
+void GLSL_BindProgram(shaderProgram_t * program)
+{
+ if(!program)
+ {
+ GLSL_BindNullProgram();
+ return;
+ }
+
+ if(r_logFile->integer)
+ {
+ // don't just call LogComment, or we will get a call to va() every frame!
+ GLimp_LogComment(va("--- GL_BindProgram( %s ) ---\n", program->name));
+ }
+
+ if(glState.currentProgram != program)
+ {
+ qglUseProgramObjectARB(program->program);
+ glState.currentProgram = program;
+ backEnd.pc.c_glslShaderBinds++;
+ }
+}
+
+
+void GLSL_BindNullProgram(void)
+{
+ if(r_logFile->integer)
+ {
+ GLimp_LogComment("--- GL_BindNullProgram ---\n");
+ }
+
+ if(glState.currentProgram)
+ {
+ qglUseProgramObjectARB(0);
+ glState.currentProgram = NULL;
+ }
+}
+
+
+void GLSL_VertexAttribsState(uint32_t stateBits)
+{
+ uint32_t diff;
+
+ GLSL_VertexAttribPointers(stateBits);
+
+ diff = stateBits ^ glState.vertexAttribsState;
+ if(!diff)
+ {
+ return;
+ }
+
+ if(diff & ATTR_POSITION)
+ {
+ if(stateBits & ATTR_POSITION)
+ {
+ GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_POSITION )\n");
+ qglEnableVertexAttribArrayARB(ATTR_INDEX_POSITION);
+ }
+ else
+ {
+ GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_POSITION )\n");
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_POSITION);
+ }
+ }
+
+ if(diff & ATTR_TEXCOORD)
+ {
+ if(stateBits & ATTR_TEXCOORD)
+ {
+ GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_TEXCOORD )\n");
+ qglEnableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD0);
+ }
+ else
+ {
+ GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_TEXCOORD )\n");
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD0);
+ }
+ }
+
+ if(diff & ATTR_LIGHTCOORD)
+ {
+ if(stateBits & ATTR_LIGHTCOORD)
+ {
+ GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_LIGHTCOORD )\n");
+ qglEnableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD1);
+ }
+ else
+ {
+ GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_LIGHTCOORD )\n");
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD1);
+ }
+ }
+
+ if(diff & ATTR_NORMAL)
+ {
+ if(stateBits & ATTR_NORMAL)
+ {
+ GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_NORMAL )\n");
+ qglEnableVertexAttribArrayARB(ATTR_INDEX_NORMAL);
+ }
+ else
+ {
+ GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_NORMAL )\n");
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_NORMAL);
+ }
+ }
+
+#ifdef USE_VERT_TANGENT_SPACE
+ if(diff & ATTR_TANGENT)
+ {
+ if(stateBits & ATTR_TANGENT)
+ {
+ GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_TANGENT )\n");
+ qglEnableVertexAttribArrayARB(ATTR_INDEX_TANGENT);
+ }
+ else
+ {
+ GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_TANGENT )\n");
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT);
+ }
+ }
+
+ if(diff & ATTR_BITANGENT)
+ {
+ if(stateBits & ATTR_BITANGENT)
+ {
+ GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_BITANGENT )\n");
+ qglEnableVertexAttribArrayARB(ATTR_INDEX_BITANGENT);
+ }
+ else
+ {
+ GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_BITANGENT )\n");
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_BITANGENT);
+ }
+ }
+#endif
+
+ if(diff & ATTR_COLOR)
+ {
+ if(stateBits & ATTR_COLOR)
+ {
+ GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_COLOR )\n");
+ qglEnableVertexAttribArrayARB(ATTR_INDEX_COLOR);
+ }
+ else
+ {
+ GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_COLOR )\n");
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_COLOR);
+ }
+ }
+
+ if(diff & ATTR_LIGHTDIRECTION)
+ {
+ if(stateBits & ATTR_LIGHTDIRECTION)
+ {
+ GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_LIGHTDIRECTION )\n");
+ qglEnableVertexAttribArrayARB(ATTR_INDEX_LIGHTDIRECTION);
+ }
+ else
+ {
+ GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_LIGHTDIRECTION )\n");
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_LIGHTDIRECTION);
+ }
+ }
+
+ if(diff & ATTR_POSITION2)
+ {
+ if(stateBits & ATTR_POSITION2)
+ {
+ GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_POSITION2 )\n");
+ qglEnableVertexAttribArrayARB(ATTR_INDEX_POSITION2);
+ }
+ else
+ {
+ GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_POSITION2 )\n");
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_POSITION2);
+ }
+ }
+
+ if(diff & ATTR_NORMAL2)
+ {
+ if(stateBits & ATTR_NORMAL2)
+ {
+ GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_NORMAL2 )\n");
+ qglEnableVertexAttribArrayARB(ATTR_INDEX_NORMAL2);
+ }
+ else
+ {
+ GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_NORMAL2 )\n");
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_NORMAL2);
+ }
+ }
+
+#ifdef USE_VERT_TANGENT_SPACE
+ if(diff & ATTR_TANGENT2)
+ {
+ if(stateBits & ATTR_TANGENT2)
+ {
+ GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_TANGENT2 )\n");
+ qglEnableVertexAttribArrayARB(ATTR_INDEX_TANGENT2);
+ }
+ else
+ {
+ GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_TANGENT2 )\n");
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT2);
+ }
+ }
+
+ if(diff & ATTR_BITANGENT2)
+ {
+ if(stateBits & ATTR_BITANGENT2)
+ {
+ GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_BITANGENT2 )\n");
+ qglEnableVertexAttribArrayARB(ATTR_INDEX_BITANGENT2);
+ }
+ else
+ {
+ GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_BITANGENT2 )\n");
+ qglDisableVertexAttribArrayARB(ATTR_INDEX_BITANGENT2);
+ }
+ }
+#endif
+
+ glState.vertexAttribsState = stateBits;
+}
+
+void GLSL_VertexAttribPointers(uint32_t attribBits)
+{
+ if(!glState.currentVBO)
+ {
+ ri.Error(ERR_FATAL, "GL_VertexAttribPointers: no VBO bound");
+ return;
+ }
+
+ // don't just call LogComment, or we will get a call to va() every frame!
+ GLimp_LogComment(va("--- GL_VertexAttribPointers( %s ) ---\n", glState.currentVBO->name));
+
+ if((attribBits & ATTR_POSITION) && !(glState.vertexAttribPointersSet & ATTR_POSITION))
+ {
+ GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_POSITION )\n");
+
+ qglVertexAttribPointerARB(ATTR_INDEX_POSITION, 3, GL_FLOAT, 0, glState.currentVBO->stride_xyz, BUFFER_OFFSET(glState.currentVBO->ofs_xyz + glState.vertexAttribsNewFrame * glState.currentVBO->size_xyz));
+ glState.vertexAttribPointersSet |= ATTR_POSITION;
+ }
+
+ if((attribBits & ATTR_TEXCOORD) && !(glState.vertexAttribPointersSet & ATTR_TEXCOORD))
+ {
+ GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_TEXCOORD )\n");
+
+ qglVertexAttribPointerARB(ATTR_INDEX_TEXCOORD0, 2, GL_FLOAT, 0, glState.currentVBO->stride_st, BUFFER_OFFSET(glState.currentVBO->ofs_st));
+ glState.vertexAttribPointersSet |= ATTR_TEXCOORD;
+ }
+
+ if((attribBits & ATTR_LIGHTCOORD) && !(glState.vertexAttribPointersSet & ATTR_LIGHTCOORD))
+ {
+ GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_LIGHTCOORD )\n");
+
+ qglVertexAttribPointerARB(ATTR_INDEX_TEXCOORD1, 2, GL_FLOAT, 0, glState.currentVBO->stride_lightmap, BUFFER_OFFSET(glState.currentVBO->ofs_lightmap));
+ glState.vertexAttribPointersSet |= ATTR_LIGHTCOORD;
+ }
+
+ if((attribBits & ATTR_NORMAL) && !(glState.vertexAttribPointersSet & ATTR_NORMAL))
+ {
+ GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_NORMAL )\n");
+
+ qglVertexAttribPointerARB(ATTR_INDEX_NORMAL, 3, GL_FLOAT, 0, glState.currentVBO->stride_normal, BUFFER_OFFSET(glState.currentVBO->ofs_normal + glState.vertexAttribsNewFrame * glState.currentVBO->size_normal));
+ glState.vertexAttribPointersSet |= ATTR_NORMAL;
+ }
+
+#ifdef USE_VERT_TANGENT_SPACE
+ if((attribBits & ATTR_TANGENT) && !(glState.vertexAttribPointersSet & ATTR_TANGENT))
+ {
+ GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_TANGENT )\n");
+
+ qglVertexAttribPointerARB(ATTR_INDEX_TANGENT, 3, GL_FLOAT, 0, glState.currentVBO->stride_tangent, BUFFER_OFFSET(glState.currentVBO->ofs_tangent + glState.vertexAttribsNewFrame * glState.currentVBO->size_normal)); // FIXME
+ glState.vertexAttribPointersSet |= ATTR_TANGENT;
+ }
+
+ if((attribBits & ATTR_BITANGENT) && !(glState.vertexAttribPointersSet & ATTR_BITANGENT))
+ {
+ GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_BITANGENT )\n");
+
+ qglVertexAttribPointerARB(ATTR_INDEX_BITANGENT, 3, GL_FLOAT, 0, glState.currentVBO->stride_bitangent, BUFFER_OFFSET(glState.currentVBO->ofs_bitangent + glState.vertexAttribsNewFrame * glState.currentVBO->size_normal)); // FIXME
+ glState.vertexAttribPointersSet |= ATTR_BITANGENT;
+ }
+#endif
+
+ if((attribBits & ATTR_COLOR) && !(glState.vertexAttribPointersSet & ATTR_COLOR))
+ {
+ GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_COLOR )\n");
+
+ qglVertexAttribPointerARB(ATTR_INDEX_COLOR, 4, GL_FLOAT, 0, glState.currentVBO->stride_vertexcolor, BUFFER_OFFSET(glState.currentVBO->ofs_vertexcolor));
+ glState.vertexAttribPointersSet |= ATTR_COLOR;
+ }
+
+ if((attribBits & ATTR_LIGHTDIRECTION) && !(glState.vertexAttribPointersSet & ATTR_LIGHTDIRECTION))
+ {
+ GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_LIGHTDIRECTION )\n");
+
+ qglVertexAttribPointerARB(ATTR_INDEX_LIGHTDIRECTION, 3, GL_FLOAT, 0, glState.currentVBO->stride_lightdir, BUFFER_OFFSET(glState.currentVBO->ofs_lightdir));
+ glState.vertexAttribPointersSet |= ATTR_LIGHTDIRECTION;
+ }
+
+ if((attribBits & ATTR_POSITION2) && !(glState.vertexAttribPointersSet & ATTR_POSITION2))
+ {
+ GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_POSITION2 )\n");
+
+ qglVertexAttribPointerARB(ATTR_INDEX_POSITION2, 3, GL_FLOAT, 0, glState.currentVBO->stride_xyz, BUFFER_OFFSET(glState.currentVBO->ofs_xyz + glState.vertexAttribsOldFrame * glState.currentVBO->size_xyz));
+ glState.vertexAttribPointersSet |= ATTR_POSITION2;
+ }
+
+ if((attribBits & ATTR_NORMAL2) && !(glState.vertexAttribPointersSet & ATTR_NORMAL2))
+ {
+ GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_NORMAL2 )\n");
+
+ qglVertexAttribPointerARB(ATTR_INDEX_NORMAL2, 3, GL_FLOAT, 0, glState.currentVBO->stride_normal, BUFFER_OFFSET(glState.currentVBO->ofs_normal + glState.vertexAttribsOldFrame * glState.currentVBO->size_normal));
+ glState.vertexAttribPointersSet |= ATTR_NORMAL2;
+ }
+
+#ifdef USE_VERT_TANGENT_SPACE
+ if((attribBits & ATTR_TANGENT2) && !(glState.vertexAttribPointersSet & ATTR_TANGENT2))
+ {
+ GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_TANGENT2 )\n");
+
+ qglVertexAttribPointerARB(ATTR_INDEX_TANGENT2, 3, GL_FLOAT, 0, glState.currentVBO->stride_tangent, BUFFER_OFFSET(glState.currentVBO->ofs_tangent + glState.vertexAttribsOldFrame * glState.currentVBO->size_normal)); // FIXME
+ glState.vertexAttribPointersSet |= ATTR_TANGENT2;
+ }
+
+ if((attribBits & ATTR_BITANGENT2) && !(glState.vertexAttribPointersSet & ATTR_BITANGENT2))
+ {
+ GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_BITANGENT2 )\n");
+
+ qglVertexAttribPointerARB(ATTR_INDEX_BITANGENT2, 3, GL_FLOAT, 0, glState.currentVBO->stride_bitangent, BUFFER_OFFSET(glState.currentVBO->ofs_bitangent + glState.vertexAttribsOldFrame * glState.currentVBO->size_normal)); // FIXME
+ glState.vertexAttribPointersSet |= ATTR_BITANGENT2;
+ }
+#endif
+
+}
+
+shaderProgram_t *GLSL_GetGenericShaderProgram(int stage)
+{
+ shaderStage_t *pStage = tess.xstages[stage];
+ int shaderAttribs = 0;
+
+ if (tess.fogNum && pStage->adjustColorsForFog)
+ {
+ shaderAttribs |= GENERICDEF_USE_FOG;
+ }
+
+ if (pStage->bundle[1].image[0] && tess.shader->multitextureEnv)
+ {
+ shaderAttribs |= GENERICDEF_USE_LIGHTMAP;
+ }
+
+ switch (pStage->rgbGen)
+ {
+ case CGEN_LIGHTING_DIFFUSE:
+ shaderAttribs |= GENERICDEF_USE_RGBAGEN;
+ break;
+ default:
+ break;
+ }
+
+ switch (pStage->alphaGen)
+ {
+ case AGEN_LIGHTING_SPECULAR:
+ case AGEN_PORTAL:
+ case AGEN_FRESNEL:
+ shaderAttribs |= GENERICDEF_USE_RGBAGEN;
+ break;
+ default:
+ break;
+ }
+
+ if (pStage->bundle[0].tcGen != TCGEN_TEXTURE)
+ {
+ shaderAttribs |= GENERICDEF_USE_TCGEN;
+ }
+
+ if (tess.shader->numDeforms && !ShaderRequiresCPUDeforms(tess.shader))
+ {
+ shaderAttribs |= GENERICDEF_USE_DEFORM_VERTEXES;
+ }
+
+ if (glState.vertexAttribsInterpolation > 0.0f && backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity)
+ {
+ shaderAttribs |= GENERICDEF_USE_VERTEX_ANIMATION;
+ }
+
+ return &tr.genericShader[shaderAttribs];
+}