From 24e97e5ba02d49555cd02774186114e616750762 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Wed, 9 Jul 2014 17:38:57 -0700 Subject: Update Warsow shaders to 1.5.0. $ warsow +timedemo 1 +cg_showFPS 1 +cl_checkForUpdate 0 \ +demo pts1 +next "quit" --- shaders/warsow/1.shader_test | 2310 +++++++++++++---- shaders/warsow/10.shader_test | 1968 +++++++++++---- shaders/warsow/100.shader_test | 1673 +++++++++++++ shaders/warsow/103.shader_test | 2057 ++++++++++++++++ shaders/warsow/106.shader_test | 2059 ++++++++++++++++ shaders/warsow/109.shader_test | 1753 +++++++++++++ shaders/warsow/112.shader_test | 2061 ++++++++++++++++ shaders/warsow/115.shader_test | 2055 ++++++++++++++++ shaders/warsow/118.shader_test | 1675 +++++++++++++ shaders/warsow/121.shader_test | 2057 ++++++++++++++++ shaders/warsow/124.shader_test | 1239 ++++++++++ shaders/warsow/127.shader_test | 2059 ++++++++++++++++ shaders/warsow/13.shader_test | 1508 ++++++++---- shaders/warsow/130.shader_test | 2057 ++++++++++++++++ shaders/warsow/133.shader_test | 1419 +++++++++++ shaders/warsow/136.shader_test | 2059 ++++++++++++++++ shaders/warsow/139.shader_test | 1675 +++++++++++++ shaders/warsow/142.shader_test | 1753 +++++++++++++ shaders/warsow/145.shader_test | 2063 ++++++++++++++++ shaders/warsow/148.shader_test | 2061 ++++++++++++++++ shaders/warsow/151.shader_test | 1753 +++++++++++++ shaders/warsow/154.shader_test | 1421 +++++++++++ shaders/warsow/157.shader_test | 1431 +++++++++++ shaders/warsow/16.shader_test | 1810 ++++++++++++-- shaders/warsow/160.shader_test | 1431 +++++++++++ shaders/warsow/163.shader_test | 2061 ++++++++++++++++ shaders/warsow/166.shader_test | 2061 ++++++++++++++++ shaders/warsow/169.shader_test | 1753 +++++++++++++ shaders/warsow/172.shader_test | 1753 +++++++++++++ shaders/warsow/175.shader_test | 1755 +++++++++++++ shaders/warsow/178.shader_test | 2059 ++++++++++++++++ shaders/warsow/181.shader_test | 2059 ++++++++++++++++ shaders/warsow/184.shader_test | 2057 ++++++++++++++++ shaders/warsow/187.shader_test | 1751 +++++++++++++ shaders/warsow/19.shader_test | 1440 ++++++++++- shaders/warsow/190.shader_test | 2061 ++++++++++++++++ shaders/warsow/193.shader_test | 1753 +++++++++++++ shaders/warsow/196.shader_test | 1675 +++++++++++++ shaders/warsow/199.shader_test | 1241 ++++++++++ shaders/warsow/202.shader_test | 1755 +++++++++++++ shaders/warsow/205.shader_test | 2084 ++++++++++++++++ shaders/warsow/208.shader_test | 1698 +++++++++++++ shaders/warsow/211.shader_test | 1793 ++++++++++++++ shaders/warsow/214.shader_test | 1784 ++++++++++++++ shaders/warsow/217.shader_test | 1782 ++++++++++++++ shaders/warsow/22.shader_test | 1100 ++++++++- shaders/warsow/220.shader_test | 1784 ++++++++++++++ shaders/warsow/223.shader_test | 1797 ++++++++++++++ shaders/warsow/226.shader_test | 1784 ++++++++++++++ shaders/warsow/229.shader_test | 1795 ++++++++++++++ shaders/warsow/232.shader_test | 1784 ++++++++++++++ shaders/warsow/235.shader_test | 2063 ++++++++++++++++ shaders/warsow/238.shader_test | 2059 ++++++++++++++++ shaders/warsow/241.shader_test | 1421 +++++++++++ shaders/warsow/244.shader_test | 1421 +++++++++++ shaders/warsow/247.shader_test | 1675 +++++++++++++ shaders/warsow/25.shader_test | 5301 +++++++++++++++++++++++++++++++++++++++- shaders/warsow/250.shader_test | 1675 +++++++++++++ shaders/warsow/253.shader_test | 1698 +++++++++++++ shaders/warsow/256.shader_test | 1677 +++++++++++++ shaders/warsow/259.shader_test | 1675 +++++++++++++ shaders/warsow/262.shader_test | 1795 ++++++++++++++ shaders/warsow/28.shader_test | 1031 ++++++++ shaders/warsow/30.shader_test | 26 - shaders/warsow/31.shader_test | 2312 ++++++++++++++---- shaders/warsow/34.shader_test | 2322 ++++++++++++++---- shaders/warsow/37.shader_test | 2326 ++++++++++++++---- shaders/warsow/4.shader_test | 1528 ++++++++---- shaders/warsow/40.shader_test | 1976 +++++++++++---- shaders/warsow/43.shader_test | 1972 +++++++++++---- shaders/warsow/46.shader_test | 1816 ++++++++++++-- shaders/warsow/49.shader_test | 2094 +++++++++++++++- shaders/warsow/52.shader_test | 2048 +++++++++++++++- shaders/warsow/55.shader_test | 1273 +++++++++- shaders/warsow/58.shader_test | 1751 +++++++++++++ shaders/warsow/60.shader_test | 17 - shaders/warsow/61.shader_test | 2057 ++++++++++++++++ shaders/warsow/63.shader_test | 22 - shaders/warsow/64.shader_test | 1979 +++++++++++---- shaders/warsow/67.shader_test | 2322 ++++++++++++++---- shaders/warsow/7.shader_test | 1290 ++++++---- shaders/warsow/70.shader_test | 1514 ++++++++---- shaders/warsow/73.shader_test | 2328 ++++++++++++++---- shaders/warsow/76.shader_test | 1518 ++++++++---- shaders/warsow/79.shader_test | 2326 ++++++++++++++---- shaders/warsow/82.shader_test | 2120 ++++++++++++++-- shaders/warsow/85.shader_test | 2090 +++++++++++++++- shaders/warsow/88.shader_test | 2050 +++++++++++++++- shaders/warsow/91.shader_test | 2056 +++++++++++++++- shaders/warsow/94.shader_test | 2059 ++++++++++++++++ shaders/warsow/97.shader_test | 2057 ++++++++++++++++ 91 files changed, 155616 insertions(+), 8950 deletions(-) create mode 100644 shaders/warsow/100.shader_test create mode 100644 shaders/warsow/103.shader_test create mode 100644 shaders/warsow/106.shader_test create mode 100644 shaders/warsow/109.shader_test create mode 100644 shaders/warsow/112.shader_test create mode 100644 shaders/warsow/115.shader_test create mode 100644 shaders/warsow/118.shader_test create mode 100644 shaders/warsow/121.shader_test create mode 100644 shaders/warsow/124.shader_test create mode 100644 shaders/warsow/127.shader_test create mode 100644 shaders/warsow/130.shader_test create mode 100644 shaders/warsow/133.shader_test create mode 100644 shaders/warsow/136.shader_test create mode 100644 shaders/warsow/139.shader_test create mode 100644 shaders/warsow/142.shader_test create mode 100644 shaders/warsow/145.shader_test create mode 100644 shaders/warsow/148.shader_test create mode 100644 shaders/warsow/151.shader_test create mode 100644 shaders/warsow/154.shader_test create mode 100644 shaders/warsow/157.shader_test create mode 100644 shaders/warsow/160.shader_test create mode 100644 shaders/warsow/163.shader_test create mode 100644 shaders/warsow/166.shader_test create mode 100644 shaders/warsow/169.shader_test create mode 100644 shaders/warsow/172.shader_test create mode 100644 shaders/warsow/175.shader_test create mode 100644 shaders/warsow/178.shader_test create mode 100644 shaders/warsow/181.shader_test create mode 100644 shaders/warsow/184.shader_test create mode 100644 shaders/warsow/187.shader_test create mode 100644 shaders/warsow/190.shader_test create mode 100644 shaders/warsow/193.shader_test create mode 100644 shaders/warsow/196.shader_test create mode 100644 shaders/warsow/199.shader_test create mode 100644 shaders/warsow/202.shader_test create mode 100644 shaders/warsow/205.shader_test create mode 100644 shaders/warsow/208.shader_test create mode 100644 shaders/warsow/211.shader_test create mode 100644 shaders/warsow/214.shader_test create mode 100644 shaders/warsow/217.shader_test create mode 100644 shaders/warsow/220.shader_test create mode 100644 shaders/warsow/223.shader_test create mode 100644 shaders/warsow/226.shader_test create mode 100644 shaders/warsow/229.shader_test create mode 100644 shaders/warsow/232.shader_test create mode 100644 shaders/warsow/235.shader_test create mode 100644 shaders/warsow/238.shader_test create mode 100644 shaders/warsow/241.shader_test create mode 100644 shaders/warsow/244.shader_test create mode 100644 shaders/warsow/247.shader_test create mode 100644 shaders/warsow/250.shader_test create mode 100644 shaders/warsow/253.shader_test create mode 100644 shaders/warsow/256.shader_test create mode 100644 shaders/warsow/259.shader_test create mode 100644 shaders/warsow/262.shader_test create mode 100644 shaders/warsow/28.shader_test delete mode 100644 shaders/warsow/30.shader_test create mode 100644 shaders/warsow/58.shader_test delete mode 100644 shaders/warsow/60.shader_test create mode 100644 shaders/warsow/61.shader_test delete mode 100644 shaders/warsow/63.shader_test create mode 100644 shaders/warsow/94.shader_test create mode 100644 shaders/warsow/97.shader_test diff --git a/shaders/warsow/1.shader_test b/shaders/warsow/1.shader_test index f005219..fc589b9 100644 --- a/shaders/warsow/1.shader_test +++ b/shaders/warsow/1.shader_test @@ -1,481 +1,1789 @@ [require] GLSL >= 1.10 +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + [fragment shader] -#define FRAGMENT_SHADER -// Warsow GLSL shader +#version 130 -#if !defined(__GLSL_CG_DATA_TYPES) +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -void main() +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; -#endif -#endif -#endif -#endif +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; -#endif +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; -#endif +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; -#endif +vec4 DQReal1, DQDual1; +float scale; -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +if (numWeights > 2) { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} } +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -void main() -{ -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +uniform float u_ShaderTime; -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); -#else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; -#endif +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; -#endif +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors -// deluxemapping using light vectors in modelspace +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; -#ifdef APPLY_LIGHTSTYLE0 +uniform myhalf2 u_BlendMix; -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +uniform float u_MirrorSide; -#define NORMALIZE_DIFFUSE_NORMAL +uniform float u_ZNear, u_ZFar; -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); -#endif +uniform ivec4 u_Viewport; // x, y, width, height -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; -#endif +uniform vec4 u_TextureParams; -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); +uniform myhalf u_SoftParticlesScale; -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) #endif -#endif -#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); -#ifdef APPLY_SPECULAR + falloff *= falloff; -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) #else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); #endif -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); -#else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); #endif -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) +#ifdef APPLY_FOG +struct Fog { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); -} + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) #endif -#else -color = color * myhalf4(gl_Color.rgba); +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); -#else -gl_FragColor = vec4(color); +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif } -#endif // FRAGMENT_SHADER +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); -[vertex shader] -#define VERTEX_SHADER -// Warsow GLSL shader +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} -#if !defined(__GLSL_CG_DATA_TYPES) -#define myhalf float -#define myhalf2 vec2 -#define myhalf3 vec3 -#define myhalf4 vec4 -#else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 #endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; #endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; #endif +qf_varying vec3 v_Position; + #if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +qf_varying vec3 v_EyeVector; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; -#endif +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif #ifdef VERTEX_SHADER -// Vertex shader +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif -uniform vec3 EyeOrigin; +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} -void main() +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) { -gl_FrontColor = gl_Color; - -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) #endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); #endif -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); #endif -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); #endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP #endif } -#endif // VERTEX_SHADER +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); -#ifdef FRAGMENT_SHADER -// Fragment shader + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; + qf_FrontColor = vec4(outColor); -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; #endif -#endif -#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; #endif -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; #ifdef APPLY_DECAL -uniform sampler2D DecalTexture; +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; #endif #if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; +uniform float u_OffsetMappingScale; #endif -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; #endif -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor #if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) // The following reliefmapping and offsetmapping routine was taken from DarkPlaces @@ -483,207 +1791,259 @@ uniform myhalf GlossExponent; // gloss exponent factor vec2 OffsetMapping(vec2 TexCoord) { #ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING } -#endif +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) void main() { #if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; #endif -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; + myhalf3 weightedDiffuseNormalModelspace; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); #ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); #else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; -#endif +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; #endif -// deluxemapping using light vectors in modelspace +#endif // APPLY_CELSHADING -#ifdef APPLY_LIGHTSTYLE0 +#endif // APPLY_DIRECTIONAL_LIGHT -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); #ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); #else - #define NORMALIZE_DIFFUSE_NORMAL - -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); -#endif + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP #ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; -#endif - -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); - -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); - -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); - -#endif -#endif -#endif + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); #endif #ifdef APPLY_SPECULAR #ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); #else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); #endif -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); -#endif + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); #else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); -#endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); #endif +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + #ifdef APPLY_DECAL + #ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); #else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) -{ -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); -} -#endif + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + #else -color = color * myhalf4(gl_Color.rgba); -#endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; #else -gl_FragColor = vec4(color); + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); #endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); } #endif // FRAGMENT_SHADER - diff --git a/shaders/warsow/10.shader_test b/shaders/warsow/10.shader_test index de4bd35..93aaa73 100644 --- a/shaders/warsow/10.shader_test +++ b/shaders/warsow/10.shader_test @@ -1,695 +1,1669 @@ [require] GLSL >= 1.10 -[fragment shader] -#define FRAGMENT_SHADER -#define APPLY_LIGHTSTYLE0 -#define APPLY_FBLIGHTMAP -#define APPLY_SPECULAR -#define APPLY_AMBIENT_COMPENSATION -// Warsow GLSL shader - -#if !defined(__GLSL_CG_DATA_TYPES) +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 #endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -void main() +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; -#endif -#endif -#endif -#endif +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; -#endif +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; -#endif +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; -#endif +vec4 DQReal1, DQDual1; +float scale; -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +if (numWeights > 2) { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} } + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -void main() -{ -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +uniform float u_ShaderTime; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); -#else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; -#endif +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors -#endif +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; -// deluxemapping using light vectors in modelspace +uniform myhalf2 u_BlendMix; -#ifdef APPLY_LIGHTSTYLE0 +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +uniform float u_MirrorSide; -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +uniform float u_ZNear, u_ZFar; -#define NORMALIZE_DIFFUSE_NORMAL +uniform ivec4 u_Viewport; // x, y, width, height -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); -#endif +uniform vec4 u_TextureParams; -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) #endif -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); +#ifndef NUM_SHADOWS +#define NUM_SHADOWS 1 +#endif -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS]; -#endif -#endif -#endif +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); #endif -#ifdef APPLY_SPECULAR +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); -#else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); #endif -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); -#else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) + +uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS]; + +void main(void) { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + + for (int i = 0; i < NUM_SHADOWS; i++) + { + v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position; + // a trick whish allows us not to perform the + // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)' + // computation in the fragment shader + v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5; + } } -#endif -#else -color = color * myhalf4(gl_Color.rgba); -#endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_RGB_SHADOW +uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy))) #else -gl_FragColor = vec4(color); +uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) float(qf_shadow(t,v)) #endif + +uniform float u_ShadowAlpha; +uniform float u_ShadowProjDistance[NUM_SHADOWS]; +uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS]; + +void main(void) +{ + float finalcolor = 1.0; + +#if NUM_SHADOWS >= 1 +#define SHADOW_INDEX 0 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 2 +#define SHADOW_INDEX 1 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 3 +#define SHADOW_INDEX 2 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 4 +#define SHADOW_INDEX 3 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + + qf_FragColor = vec4(vec3(finalcolor),1.0); } #endif // FRAGMENT_SHADER -[vertex shader] -#define VERTEX_SHADER -#define APPLY_LIGHTSTYLE0 -#define APPLY_FBLIGHTMAP -#define APPLY_SPECULAR -#define APPLY_AMBIENT_COMPENSATION -// Warsow GLSL shader +[fragment shader] +#version 130 -#if !defined(__GLSL_CG_DATA_TYPES) +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 #endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -void main() +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; -#endif -#endif -#endif -#endif +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; -#endif +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; -#endif +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; -#endif +vec4 DQReal1, DQDual1; +float scale; -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +if (numWeights > 2) { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} } +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -void main() -{ -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +uniform float u_ShaderTime; -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); -#else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; -#endif +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; -#endif +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors -// deluxemapping using light vectors in modelspace +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; -#ifdef APPLY_LIGHTSTYLE0 +uniform myhalf2 u_BlendMix; -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +uniform float u_MirrorSide; -#define NORMALIZE_DIFFUSE_NORMAL +uniform float u_ZNear, u_ZFar; -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); -#endif +uniform ivec4 u_Viewport; // x, y, width, height -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) #endif -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); +#ifndef NUM_SHADOWS +#define NUM_SHADOWS 1 +#endif -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS]; -#endif -#endif -#endif +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); #endif -#ifdef APPLY_SPECULAR +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); -#else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); #endif -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); -#else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) + +uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS]; + +void main(void) { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + + for (int i = 0; i < NUM_SHADOWS; i++) + { + v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position; + // a trick whish allows us not to perform the + // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)' + // computation in the fragment shader + v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5; + } } -#endif -#else -color = color * myhalf4(gl_Color.rgba); -#endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_RGB_SHADOW +uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy))) #else -gl_FragColor = vec4(color); +uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) float(qf_shadow(t,v)) #endif + +uniform float u_ShadowAlpha; +uniform float u_ShadowProjDistance[NUM_SHADOWS]; +uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS]; + +void main(void) +{ + float finalcolor = 1.0; + +#if NUM_SHADOWS >= 1 +#define SHADOW_INDEX 0 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 2 +#define SHADOW_INDEX 1 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 3 +#define SHADOW_INDEX 2 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 4 +#define SHADOW_INDEX 3 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + + qf_FragColor = vec4(vec3(finalcolor),1.0); } #endif // FRAGMENT_SHADER diff --git a/shaders/warsow/100.shader_test b/shaders/warsow/100.shader_test new file mode 100644 index 0000000..ff9a2dc --- /dev/null +++ b/shaders/warsow/100.shader_test @@ -0,0 +1,1673 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_PCF + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) +#endif + + +#ifndef NUM_SHADOWS +#define NUM_SHADOWS 1 +#endif + +qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS]; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS]; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + + for (int i = 0; i < NUM_SHADOWS; i++) + { + v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position; + // a trick whish allows us not to perform the + // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)' + // computation in the fragment shader + v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5; + } +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_RGB_SHADOW +uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy))) +#else +uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) float(qf_shadow(t,v)) +#endif + +uniform float u_ShadowAlpha; +uniform float u_ShadowProjDistance[NUM_SHADOWS]; +uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS]; + +void main(void) +{ + float finalcolor = 1.0; + +#if NUM_SHADOWS >= 1 +#define SHADOW_INDEX 0 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 2 +#define SHADOW_INDEX 1 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 3 +#define SHADOW_INDEX 2 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 4 +#define SHADOW_INDEX 3 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + + qf_FragColor = vec4(vec3(finalcolor),1.0); +} + +#endif // FRAGMENT_SHADER + + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_PCF + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) +#endif + + +#ifndef NUM_SHADOWS +#define NUM_SHADOWS 1 +#endif + +qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS]; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS]; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + + for (int i = 0; i < NUM_SHADOWS; i++) + { + v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position; + // a trick whish allows us not to perform the + // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)' + // computation in the fragment shader + v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5; + } +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_RGB_SHADOW +uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy))) +#else +uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) float(qf_shadow(t,v)) +#endif + +uniform float u_ShadowAlpha; +uniform float u_ShadowProjDistance[NUM_SHADOWS]; +uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS]; + +void main(void) +{ + float finalcolor = 1.0; + +#if NUM_SHADOWS >= 1 +#define SHADOW_INDEX 0 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 2 +#define SHADOW_INDEX 1 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 3 +#define SHADOW_INDEX 2 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 4 +#define SHADOW_INDEX 3 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + + qf_FragColor = vec4(vec3(finalcolor),1.0); +} + +#endif // FRAGMENT_SHADER + + diff --git a/shaders/warsow/103.shader_test b/shaders/warsow/103.shader_test new file mode 100644 index 0000000..1f311c4 --- /dev/null +++ b/shaders/warsow/103.shader_test @@ -0,0 +1,2057 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_LIGHTMAPS 1 +#define APPLY_RELIEFMAPPING + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_LIGHTMAPS 1 +#define APPLY_RELIEFMAPPING + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/106.shader_test b/shaders/warsow/106.shader_test new file mode 100644 index 0000000..f233b69 --- /dev/null +++ b/shaders/warsow/106.shader_test @@ -0,0 +1,2059 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_LIGHTMAPS 1 +#define APPLY_SPECULAR +#define APPLY_RELIEFMAPPING + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_LIGHTMAPS 1 +#define APPLY_SPECULAR +#define APPLY_RELIEFMAPPING + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/109.shader_test b/shaders/warsow/109.shader_test new file mode 100644 index 0000000..08ae3bb --- /dev/null +++ b/shaders/warsow/109.shader_test @@ -0,0 +1,1753 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_CONST +#define NUM_DLIGHTS 4 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_CONST +#define NUM_DLIGHTS 4 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/112.shader_test b/shaders/warsow/112.shader_test new file mode 100644 index 0000000..baa52fe --- /dev/null +++ b/shaders/warsow/112.shader_test @@ -0,0 +1,2061 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX +#define NUM_DLIGHTS 4 +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_RELIEFMAPPING +#define APPLY_DIRECTIONAL_LIGHT_MIX + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX +#define NUM_DLIGHTS 4 +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_RELIEFMAPPING +#define APPLY_DIRECTIONAL_LIGHT_MIX + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/115.shader_test b/shaders/warsow/115.shader_test new file mode 100644 index 0000000..9312ee6 --- /dev/null +++ b/shaders/warsow/115.shader_test @@ -0,0 +1,2055 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_LIGHTMAPS 1 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_LIGHTMAPS 1 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/118.shader_test b/shaders/warsow/118.shader_test new file mode 100644 index 0000000..ac1d742 --- /dev/null +++ b/shaders/warsow/118.shader_test @@ -0,0 +1,1675 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_PCF +#define NUM_SHADOWS 2 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) +#endif + + +#ifndef NUM_SHADOWS +#define NUM_SHADOWS 1 +#endif + +qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS]; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS]; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + + for (int i = 0; i < NUM_SHADOWS; i++) + { + v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position; + // a trick whish allows us not to perform the + // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)' + // computation in the fragment shader + v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5; + } +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_RGB_SHADOW +uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy))) +#else +uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) float(qf_shadow(t,v)) +#endif + +uniform float u_ShadowAlpha; +uniform float u_ShadowProjDistance[NUM_SHADOWS]; +uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS]; + +void main(void) +{ + float finalcolor = 1.0; + +#if NUM_SHADOWS >= 1 +#define SHADOW_INDEX 0 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 2 +#define SHADOW_INDEX 1 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 3 +#define SHADOW_INDEX 2 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 4 +#define SHADOW_INDEX 3 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + + qf_FragColor = vec4(vec3(finalcolor),1.0); +} + +#endif // FRAGMENT_SHADER + + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_PCF +#define NUM_SHADOWS 2 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) +#endif + + +#ifndef NUM_SHADOWS +#define NUM_SHADOWS 1 +#endif + +qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS]; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS]; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + + for (int i = 0; i < NUM_SHADOWS; i++) + { + v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position; + // a trick whish allows us not to perform the + // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)' + // computation in the fragment shader + v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5; + } +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_RGB_SHADOW +uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy))) +#else +uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) float(qf_shadow(t,v)) +#endif + +uniform float u_ShadowAlpha; +uniform float u_ShadowProjDistance[NUM_SHADOWS]; +uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS]; + +void main(void) +{ + float finalcolor = 1.0; + +#if NUM_SHADOWS >= 1 +#define SHADOW_INDEX 0 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 2 +#define SHADOW_INDEX 1 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 3 +#define SHADOW_INDEX 2 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 4 +#define SHADOW_INDEX 3 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + + qf_FragColor = vec4(vec3(finalcolor),1.0); +} + +#endif // FRAGMENT_SHADER + + diff --git a/shaders/warsow/121.shader_test b/shaders/warsow/121.shader_test new file mode 100644 index 0000000..db7e332 --- /dev/null +++ b/shaders/warsow/121.shader_test @@ -0,0 +1,2057 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_HALFLAMBERT + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_HALFLAMBERT + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/124.shader_test b/shaders/warsow/124.shader_test new file mode 100644 index 0000000..3518fbc --- /dev/null +++ b/shaders/warsow/124.shader_test @@ -0,0 +1,1239 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +uniform float u_OutlineHeight; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + Position += vec4(Normal * u_OutlineHeight, 0.0); + gl_Position = u_ModelViewProjectionMatrix * Position; + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG + myhalf4 tempColor = myhalf4(1.0); + FogGen(Position, tempColor, myhalf2(0.0, 1.0)); + outColor.rgb = mix(u_Fog.Color, outColor.rgb, tempColor.a); +#endif + + qf_FrontColor = vec4(outColor); +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform float u_OutlineCutOff; + +void main(void) +{ +#ifdef APPLY_OUTLINES_CUTOFF + if (u_OutlineCutOff > 0.0 && (gl_FragCoord.z / gl_FragCoord.w > u_OutlineCutOff)) + discard; +#endif + qf_FragColor = vec4(qf_FrontColor); +} + +#endif // FRAGMENT_SHADER + + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +uniform float u_OutlineHeight; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + Position += vec4(Normal * u_OutlineHeight, 0.0); + gl_Position = u_ModelViewProjectionMatrix * Position; + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG + myhalf4 tempColor = myhalf4(1.0); + FogGen(Position, tempColor, myhalf2(0.0, 1.0)); + outColor.rgb = mix(u_Fog.Color, outColor.rgb, tempColor.a); +#endif + + qf_FrontColor = vec4(outColor); +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform float u_OutlineCutOff; + +void main(void) +{ +#ifdef APPLY_OUTLINES_CUTOFF + if (u_OutlineCutOff > 0.0 && (gl_FragCoord.z / gl_FragCoord.w > u_OutlineCutOff)) + discard; +#endif + qf_FragColor = vec4(qf_FrontColor); +} + +#endif // FRAGMENT_SHADER + + diff --git a/shaders/warsow/127.shader_test b/shaders/warsow/127.shader_test new file mode 100644 index 0000000..dd7da3c --- /dev/null +++ b/shaders/warsow/127.shader_test @@ -0,0 +1,2059 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_DLIGHTS 4 +#define NUM_LIGHTMAPS 1 +#define APPLY_SPECULAR + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_DLIGHTS 4 +#define NUM_LIGHTMAPS 1 +#define APPLY_SPECULAR + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/13.shader_test b/shaders/warsow/13.shader_test index 4a2358e..de78c04 100644 --- a/shaders/warsow/13.shader_test +++ b/shaders/warsow/13.shader_test @@ -1,691 +1,1233 @@ [require] GLSL >= 1.10 -[fragment shader] -#define FRAGMENT_SHADER -#define APPLY_DIRECTIONAL_LIGHT -#define APPLY_CELLSHADING -// Warsow GLSL shader - -#if !defined(__GLSL_CG_DATA_TYPES) +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 #endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -void main() +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; -#endif -#endif -#endif -#endif +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; -#endif +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; -#endif +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; -#endif +vec4 DQReal1, DQDual1; +float scale; -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +if (numWeights > 2) { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} } + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -void main() -{ -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +uniform float u_ShaderTime; -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); -#else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) #endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -// deluxemapping using light vectors in modelspace +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} -#ifdef APPLY_LIGHTSTYLE0 -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif -#define NORMALIZE_DIFFUSE_NORMAL +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); #endif -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); #endif -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) #endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); #endif -#ifdef APPLY_SPECULAR +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); -#else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); #endif -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); #endif -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); -#else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP #endif +} -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) + +uniform float u_OutlineHeight; + +void main(void) { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); -} -#endif -#else -color = color * myhalf4(gl_Color.rgba); + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + Position += vec4(Normal * u_OutlineHeight, 0.0); + gl_Position = u_ModelViewProjectionMatrix * Position; + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG + myhalf4 tempColor = myhalf4(1.0); + FogGen(Position, tempColor, myhalf2(0.0, 1.0)); + outColor.rgb = mix(u_Fog.Color, outColor.rgb, tempColor.a); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); -#else -gl_FragColor = vec4(color); + qf_FrontColor = vec4(outColor); +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform float u_OutlineCutOff; + +void main(void) +{ +#ifdef APPLY_OUTLINES_CUTOFF + if (u_OutlineCutOff > 0.0 && (gl_FragCoord.z / gl_FragCoord.w > u_OutlineCutOff)) + discard; #endif + qf_FragColor = vec4(qf_FrontColor); } #endif // FRAGMENT_SHADER -[vertex shader] -#define VERTEX_SHADER -#define APPLY_DIRECTIONAL_LIGHT -#define APPLY_CELLSHADING -// Warsow GLSL shader +[fragment shader] +#version 130 -#if !defined(__GLSL_CG_DATA_TYPES) +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 #endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -void main() +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; -#endif -#endif -#endif -#endif +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; -#endif +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; -#endif +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; -#endif +vec4 DQReal1, DQDual1; +float scale; -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +if (numWeights > 2) { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} } +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -void main() -{ -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +uniform float u_ShaderTime; -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); -#else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) #endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -// deluxemapping using light vectors in modelspace +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} -#ifdef APPLY_LIGHTSTYLE0 -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif -#define NORMALIZE_DIFFUSE_NORMAL +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); #endif -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); #endif -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) #endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); #endif -#ifdef APPLY_SPECULAR +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); -#else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); #endif -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); #endif -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); -#else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP #endif +} -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) + +uniform float u_OutlineHeight; + +void main(void) { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); -} -#endif -#else -color = color * myhalf4(gl_Color.rgba); + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + Position += vec4(Normal * u_OutlineHeight, 0.0); + gl_Position = u_ModelViewProjectionMatrix * Position; + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG + myhalf4 tempColor = myhalf4(1.0); + FogGen(Position, tempColor, myhalf2(0.0, 1.0)); + outColor.rgb = mix(u_Fog.Color, outColor.rgb, tempColor.a); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); -#else -gl_FragColor = vec4(color); + qf_FrontColor = vec4(outColor); +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform float u_OutlineCutOff; + +void main(void) +{ +#ifdef APPLY_OUTLINES_CUTOFF + if (u_OutlineCutOff > 0.0 && (gl_FragCoord.z / gl_FragCoord.w > u_OutlineCutOff)) + discard; #endif + qf_FragColor = vec4(qf_FrontColor); } #endif // FRAGMENT_SHADER diff --git a/shaders/warsow/130.shader_test b/shaders/warsow/130.shader_test new file mode 100644 index 0000000..be9ef9c --- /dev/null +++ b/shaders/warsow/130.shader_test @@ -0,0 +1,2057 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_DLIGHTS 4 +#define NUM_LIGHTMAPS 1 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_DLIGHTS 4 +#define NUM_LIGHTMAPS 1 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/133.shader_test b/shaders/warsow/133.shader_test new file mode 100644 index 0000000..0401722 --- /dev/null +++ b/shaders/warsow/133.shader_test @@ -0,0 +1,1419 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +qf_varying vec3 v_TexCoordCube; + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +uniform mat4 u_ReflectionTexMatrix; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#ifdef APPLY_FOG_COLOR + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); + + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform sampler2D u_BaseTexture; +uniform samplerCube u_CelShadeTexture; + +#ifdef APPLY_DIFFUSE +uniform sampler2D u_DiffuseTexture; +#endif +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif +#ifdef APPLY_STRIPES +uniform sampler2D u_StripesTexture; +#endif +#ifdef APPLY_CEL_LIGHT +uniform samplerCube u_CelLightTexture; +#endif + +void main(void) +{ + myhalf4 inColor = myhalf4(qf_FrontColor); + + myhalf4 tempColor; + + myhalf4 outColor; + outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); + +#ifdef APPLY_ENTITY_DECAL +#ifdef APPLY_ENTITY_DECAL_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_ENTITY_DECAL + +#ifdef APPLY_DIFFUSE + outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord)); +#endif + + outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube)); + +#ifdef APPLY_STRIPES +#ifdef APPLY_STRIPES_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_STRIPES_ADD + +#ifdef APPLY_CEL_LIGHT +#ifdef APPLY_CEL_LIGHT_ADD + outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); +#else + tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_CEL_LIGHT + +#ifdef APPLY_DECAL +#ifdef APPLY_DECAL_ADD + outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_DECAL + + outColor = myhalf4(inColor * outColor); + +#ifdef APPLY_GREYSCALE + outColor.rgb = Greyscale(outColor.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(outColor); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +qf_varying vec3 v_TexCoordCube; + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +uniform mat4 u_ReflectionTexMatrix; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#ifdef APPLY_FOG_COLOR + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); + + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform sampler2D u_BaseTexture; +uniform samplerCube u_CelShadeTexture; + +#ifdef APPLY_DIFFUSE +uniform sampler2D u_DiffuseTexture; +#endif +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif +#ifdef APPLY_STRIPES +uniform sampler2D u_StripesTexture; +#endif +#ifdef APPLY_CEL_LIGHT +uniform samplerCube u_CelLightTexture; +#endif + +void main(void) +{ + myhalf4 inColor = myhalf4(qf_FrontColor); + + myhalf4 tempColor; + + myhalf4 outColor; + outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); + +#ifdef APPLY_ENTITY_DECAL +#ifdef APPLY_ENTITY_DECAL_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_ENTITY_DECAL + +#ifdef APPLY_DIFFUSE + outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord)); +#endif + + outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube)); + +#ifdef APPLY_STRIPES +#ifdef APPLY_STRIPES_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_STRIPES_ADD + +#ifdef APPLY_CEL_LIGHT +#ifdef APPLY_CEL_LIGHT_ADD + outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); +#else + tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_CEL_LIGHT + +#ifdef APPLY_DECAL +#ifdef APPLY_DECAL_ADD + outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_DECAL + + outColor = myhalf4(inColor * outColor); + +#ifdef APPLY_GREYSCALE + outColor.rgb = Greyscale(outColor.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(outColor); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/136.shader_test b/shaders/warsow/136.shader_test new file mode 100644 index 0000000..442e1f2 --- /dev/null +++ b/shaders/warsow/136.shader_test @@ -0,0 +1,2059 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_DLIGHTS 4 +#define NUM_LIGHTMAPS 1 +#define APPLY_RELIEFMAPPING + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_DLIGHTS 4 +#define NUM_LIGHTMAPS 1 +#define APPLY_RELIEFMAPPING + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/139.shader_test b/shaders/warsow/139.shader_test new file mode 100644 index 0000000..de3325b --- /dev/null +++ b/shaders/warsow/139.shader_test @@ -0,0 +1,1675 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_PCF +#define NUM_SHADOWS 3 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) +#endif + + +#ifndef NUM_SHADOWS +#define NUM_SHADOWS 1 +#endif + +qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS]; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS]; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + + for (int i = 0; i < NUM_SHADOWS; i++) + { + v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position; + // a trick whish allows us not to perform the + // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)' + // computation in the fragment shader + v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5; + } +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_RGB_SHADOW +uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy))) +#else +uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) float(qf_shadow(t,v)) +#endif + +uniform float u_ShadowAlpha; +uniform float u_ShadowProjDistance[NUM_SHADOWS]; +uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS]; + +void main(void) +{ + float finalcolor = 1.0; + +#if NUM_SHADOWS >= 1 +#define SHADOW_INDEX 0 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 2 +#define SHADOW_INDEX 1 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 3 +#define SHADOW_INDEX 2 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 4 +#define SHADOW_INDEX 3 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + + qf_FragColor = vec4(vec3(finalcolor),1.0); +} + +#endif // FRAGMENT_SHADER + + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_PCF +#define NUM_SHADOWS 3 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) +#endif + + +#ifndef NUM_SHADOWS +#define NUM_SHADOWS 1 +#endif + +qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS]; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS]; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + + for (int i = 0; i < NUM_SHADOWS; i++) + { + v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position; + // a trick whish allows us not to perform the + // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)' + // computation in the fragment shader + v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5; + } +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_RGB_SHADOW +uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy))) +#else +uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) float(qf_shadow(t,v)) +#endif + +uniform float u_ShadowAlpha; +uniform float u_ShadowProjDistance[NUM_SHADOWS]; +uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS]; + +void main(void) +{ + float finalcolor = 1.0; + +#if NUM_SHADOWS >= 1 +#define SHADOW_INDEX 0 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 2 +#define SHADOW_INDEX 1 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 3 +#define SHADOW_INDEX 2 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 4 +#define SHADOW_INDEX 3 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + + qf_FragColor = vec4(vec3(finalcolor),1.0); +} + +#endif // FRAGMENT_SHADER + + diff --git a/shaders/warsow/142.shader_test b/shaders/warsow/142.shader_test new file mode 100644 index 0000000..cd94720 --- /dev/null +++ b/shaders/warsow/142.shader_test @@ -0,0 +1,1753 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX +#define APPLY_SOFT_PARTICLE + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX +#define APPLY_SOFT_PARTICLE + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/145.shader_test b/shaders/warsow/145.shader_test new file mode 100644 index 0000000..ddbb508 --- /dev/null +++ b/shaders/warsow/145.shader_test @@ -0,0 +1,2063 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 2 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_DECAL +#define APPLY_HALFLAMBERT +#define APPLY_ENTITY_DECAL + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 2 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_DECAL +#define APPLY_HALFLAMBERT +#define APPLY_ENTITY_DECAL + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/148.shader_test b/shaders/warsow/148.shader_test new file mode 100644 index 0000000..25d520f --- /dev/null +++ b/shaders/warsow/148.shader_test @@ -0,0 +1,2061 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 2 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_HALFLAMBERT +#define APPLY_ENTITY_DECAL + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 2 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_HALFLAMBERT +#define APPLY_ENTITY_DECAL + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/151.shader_test b/shaders/warsow/151.shader_test new file mode 100644 index 0000000..da69ea7 --- /dev/null +++ b/shaders/warsow/151.shader_test @@ -0,0 +1,1753 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_SOFT_PARTICLE + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_SOFT_PARTICLE + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/154.shader_test b/shaders/warsow/154.shader_test new file mode 100644 index 0000000..64b5ca9 --- /dev/null +++ b/shaders/warsow/154.shader_test @@ -0,0 +1,1421 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_DECAL + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +qf_varying vec3 v_TexCoordCube; + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +uniform mat4 u_ReflectionTexMatrix; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#ifdef APPLY_FOG_COLOR + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); + + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform sampler2D u_BaseTexture; +uniform samplerCube u_CelShadeTexture; + +#ifdef APPLY_DIFFUSE +uniform sampler2D u_DiffuseTexture; +#endif +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif +#ifdef APPLY_STRIPES +uniform sampler2D u_StripesTexture; +#endif +#ifdef APPLY_CEL_LIGHT +uniform samplerCube u_CelLightTexture; +#endif + +void main(void) +{ + myhalf4 inColor = myhalf4(qf_FrontColor); + + myhalf4 tempColor; + + myhalf4 outColor; + outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); + +#ifdef APPLY_ENTITY_DECAL +#ifdef APPLY_ENTITY_DECAL_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_ENTITY_DECAL + +#ifdef APPLY_DIFFUSE + outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord)); +#endif + + outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube)); + +#ifdef APPLY_STRIPES +#ifdef APPLY_STRIPES_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_STRIPES_ADD + +#ifdef APPLY_CEL_LIGHT +#ifdef APPLY_CEL_LIGHT_ADD + outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); +#else + tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_CEL_LIGHT + +#ifdef APPLY_DECAL +#ifdef APPLY_DECAL_ADD + outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_DECAL + + outColor = myhalf4(inColor * outColor); + +#ifdef APPLY_GREYSCALE + outColor.rgb = Greyscale(outColor.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(outColor); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_DECAL + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +qf_varying vec3 v_TexCoordCube; + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +uniform mat4 u_ReflectionTexMatrix; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#ifdef APPLY_FOG_COLOR + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); + + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform sampler2D u_BaseTexture; +uniform samplerCube u_CelShadeTexture; + +#ifdef APPLY_DIFFUSE +uniform sampler2D u_DiffuseTexture; +#endif +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif +#ifdef APPLY_STRIPES +uniform sampler2D u_StripesTexture; +#endif +#ifdef APPLY_CEL_LIGHT +uniform samplerCube u_CelLightTexture; +#endif + +void main(void) +{ + myhalf4 inColor = myhalf4(qf_FrontColor); + + myhalf4 tempColor; + + myhalf4 outColor; + outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); + +#ifdef APPLY_ENTITY_DECAL +#ifdef APPLY_ENTITY_DECAL_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_ENTITY_DECAL + +#ifdef APPLY_DIFFUSE + outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord)); +#endif + + outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube)); + +#ifdef APPLY_STRIPES +#ifdef APPLY_STRIPES_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_STRIPES_ADD + +#ifdef APPLY_CEL_LIGHT +#ifdef APPLY_CEL_LIGHT_ADD + outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); +#else + tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_CEL_LIGHT + +#ifdef APPLY_DECAL +#ifdef APPLY_DECAL_ADD + outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_DECAL + + outColor = myhalf4(inColor * outColor); + +#ifdef APPLY_GREYSCALE + outColor.rgb = Greyscale(outColor.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(outColor); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/157.shader_test b/shaders/warsow/157.shader_test new file mode 100644 index 0000000..ff46693 --- /dev/null +++ b/shaders/warsow/157.shader_test @@ -0,0 +1,1431 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 4 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_ENTITY_DECAL +#define APPLY_STRIPES +#define APPLY_CEL_LIGHT +#define APPLY_CEL_LIGHT +#define APPLY_CEL_LIGHT_ADD + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +qf_varying vec3 v_TexCoordCube; + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +uniform mat4 u_ReflectionTexMatrix; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#ifdef APPLY_FOG_COLOR + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); + + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform sampler2D u_BaseTexture; +uniform samplerCube u_CelShadeTexture; + +#ifdef APPLY_DIFFUSE +uniform sampler2D u_DiffuseTexture; +#endif +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif +#ifdef APPLY_STRIPES +uniform sampler2D u_StripesTexture; +#endif +#ifdef APPLY_CEL_LIGHT +uniform samplerCube u_CelLightTexture; +#endif + +void main(void) +{ + myhalf4 inColor = myhalf4(qf_FrontColor); + + myhalf4 tempColor; + + myhalf4 outColor; + outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); + +#ifdef APPLY_ENTITY_DECAL +#ifdef APPLY_ENTITY_DECAL_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_ENTITY_DECAL + +#ifdef APPLY_DIFFUSE + outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord)); +#endif + + outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube)); + +#ifdef APPLY_STRIPES +#ifdef APPLY_STRIPES_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_STRIPES_ADD + +#ifdef APPLY_CEL_LIGHT +#ifdef APPLY_CEL_LIGHT_ADD + outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); +#else + tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_CEL_LIGHT + +#ifdef APPLY_DECAL +#ifdef APPLY_DECAL_ADD + outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_DECAL + + outColor = myhalf4(inColor * outColor); + +#ifdef APPLY_GREYSCALE + outColor.rgb = Greyscale(outColor.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(outColor); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 4 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_ENTITY_DECAL +#define APPLY_STRIPES +#define APPLY_CEL_LIGHT +#define APPLY_CEL_LIGHT +#define APPLY_CEL_LIGHT_ADD + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +qf_varying vec3 v_TexCoordCube; + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +uniform mat4 u_ReflectionTexMatrix; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#ifdef APPLY_FOG_COLOR + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); + + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform sampler2D u_BaseTexture; +uniform samplerCube u_CelShadeTexture; + +#ifdef APPLY_DIFFUSE +uniform sampler2D u_DiffuseTexture; +#endif +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif +#ifdef APPLY_STRIPES +uniform sampler2D u_StripesTexture; +#endif +#ifdef APPLY_CEL_LIGHT +uniform samplerCube u_CelLightTexture; +#endif + +void main(void) +{ + myhalf4 inColor = myhalf4(qf_FrontColor); + + myhalf4 tempColor; + + myhalf4 outColor; + outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); + +#ifdef APPLY_ENTITY_DECAL +#ifdef APPLY_ENTITY_DECAL_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_ENTITY_DECAL + +#ifdef APPLY_DIFFUSE + outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord)); +#endif + + outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube)); + +#ifdef APPLY_STRIPES +#ifdef APPLY_STRIPES_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_STRIPES_ADD + +#ifdef APPLY_CEL_LIGHT +#ifdef APPLY_CEL_LIGHT_ADD + outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); +#else + tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_CEL_LIGHT + +#ifdef APPLY_DECAL +#ifdef APPLY_DECAL_ADD + outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_DECAL + + outColor = myhalf4(inColor * outColor); + +#ifdef APPLY_GREYSCALE + outColor.rgb = Greyscale(outColor.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(outColor); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/16.shader_test b/shaders/warsow/16.shader_test index 76c961a..ffa5bbe 100644 --- a/shaders/warsow/16.shader_test +++ b/shaders/warsow/16.shader_test @@ -1,307 +1,1747 @@ [require] GLSL >= 1.10 +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + [fragment shader] -#define FRAGMENT_SHADER -// Warsow GLSL shader +#version 130 -#if !defined(__GLSL_CG_DATA_TYPES) +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -varying vec4 TexCoord; -varying vec4 ProjVector; -#ifdef APPLY_EYEDOT -varying vec3 EyeVector; +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) #endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_EYEDOT -uniform vec3 EyeOrigin; -uniform float FrontPlane; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -void main(void) +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -mat4 textureMatrix; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -textureMatrix = gl_TextureMatrix[0]; -TexCoord.st = vec2 (textureMatrix * gl_MultiTexCoord0); +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -textureMatrix = gl_TextureMatrix[0]; -textureMatrix[0] = -textureMatrix[0]; -textureMatrix[1] = -textureMatrix[1]; -TexCoord.pq = vec2 (textureMatrix * gl_MultiTexCoord0); +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; -#ifdef APPLY_EYEDOT -mat3 strMatrix; -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif -vec3 EyeVectorWorld = (EyeOrigin - gl_Vertex.xyz) * FrontPlane; -EyeVector = EyeVectorWorld * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function -gl_Position = ftransform(); -ProjVector = gl_Position; -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} } -#endif // VERTEX_SHADER +float len = length(DQReal); +DQReal /= len; +DQDual /= len; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; -#ifdef FRAGMENT_SHADER -// Fragment shader +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif -#ifdef APPLY_DUDV -uniform sampler2D DuDvMapTexture; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} -#ifdef APPLY_EYEDOT -uniform sampler2D NormalmapTexture; +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -uniform sampler2D ReflectionTexture; -uniform sampler2D RefractionTexture; -uniform float TextureWidth, TextureHeight; +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -void main(void) +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) { -myhalf3 color; +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif -#ifdef APPLY_DUDV -vec3 displacement = vec3(texture2D(DuDvMapTexture, vec2(TexCoord.pq) * vec2(0.25))); -vec2 coord = vec2(TexCoord.st) + vec2(displacement) * vec2 (0.2); +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -vec3 fdist = vec3 (normalize(vec3(texture2D(DuDvMapTexture, coord)) - vec3 (0.5))) * vec3(0.005); +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] #else -vec3 fdist = vec3(0.0); +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + #endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; -// get projective texcoords -float scale = float(1.0 / float(ProjVector.w)); -float inv2NW = 1.0 / (2.0 * float (TextureWidth)); -float inv2NH = 1.0 / (2.0 * float (TextureHeight)); -vec2 projCoord = (vec2(ProjVector.xy) * scale + vec2 (1.0)) * vec2 (0.5) + vec2(fdist.xy); -projCoord.s = float (clamp (float(projCoord.s), inv2NW, 1.0 - inv2NW)); -projCoord.t = float (clamp (float(projCoord.t), inv2NH, 1.0 - inv2NH)); +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; -myhalf3 refr = myhalf3(0.0); -myhalf3 refl = myhalf3(0.0); +uniform myhalf2 u_BlendMix; -#ifdef APPLY_EYEDOT -// calculate dot product between the surface normal and eye vector -// great for simulating varying water translucency based on the view angle -myhalf3 surfaceNormal = normalize(myhalf3(texture2D(NormalmapTexture, coord)) - myhalf3 (0.5)); -vec3 eyeNormal = normalize(myhalf3(EyeVector)); +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) -float refrdot = float(dot(surfaceNormal, eyeNormal)); -//refrdot = float (clamp (refrdot, 0.0, 1.0)); -float refldot = 1.0 - refrdot; -// get refraction and reflection +uniform float u_MirrorSide; -#ifdef APPLY_REFRACTION -refr = (myhalf3(texture2D(RefractionTexture, projCoord))) * refrdot; +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif -#ifdef APPLY_REFLECTION -refl = (myhalf3(texture2D(ReflectionTexture, projCoord))) * refldot; +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) #endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) #else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); -#ifdef APPLY_REFRACTION -refr = (myhalf3(texture2D(RefractionTexture, projCoord))); +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) #endif -#ifdef APPLY_REFLECTION -refl = (myhalf3(texture2D(ReflectionTexture, projCoord))); + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + #endif +#endif #endif -// add reflection and refraction -#ifdef APPLY_DISTORTION_ALPHA -color = myhalf3(gl_Color.rgb) + myhalf3(mix (refr, refl, float(gl_Color.a))); -#else -color = myhalf3(gl_Color.rgb) + refr + refl; +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),1.0); -#else -gl_FragColor = vec4(vec3(color),1.0); +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif } -#endif // FRAGMENT_SHADER +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif -[vertex shader] -#define VERTEX_SHADER -// Warsow GLSL shader +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} -#if !defined(__GLSL_CG_DATA_TYPES) -#define myhalf float -#define myhalf2 vec2 -#define myhalf3 vec3 -#define myhalf4 vec4 +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +qf_varying vec2 v_TexCoord; #endif -varying vec4 TexCoord; -varying vec4 ProjVector; -#ifdef APPLY_EYEDOT -varying vec3 EyeVector; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; #endif -#ifdef VERTEX_SHADER -// Vertex shader +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif -#ifdef APPLY_EYEDOT -uniform vec3 EyeOrigin; -uniform float FrontPlane; +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; #endif -void main(void) +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) { -gl_FrontColor = gl_Color; +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif -mat4 textureMatrix; +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -textureMatrix = gl_TextureMatrix[0]; -TexCoord.st = vec2 (textureMatrix * gl_MultiTexCoord0); +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} -textureMatrix = gl_TextureMatrix[0]; -textureMatrix[0] = -textureMatrix[0]; -textureMatrix[1] = -textureMatrix[1]; -TexCoord.pq = vec2 (textureMatrix * gl_MultiTexCoord0); +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif -#ifdef APPLY_EYEDOT -mat3 strMatrix; -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -vec3 EyeVectorWorld = (EyeOrigin - gl_Vertex.xyz) * FrontPlane; -EyeVector = EyeVectorWorld * strMatrix; +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) #endif -gl_Position = ftransform(); -ProjVector = gl_Position; -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); #endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; #endif -} -#endif // VERTEX_SHADER +#endif +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif -#ifdef FRAGMENT_SHADER -// Fragment shader +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif -#ifdef APPLY_DUDV -uniform sampler2D DuDvMapTexture; + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP #endif +} + -#ifdef APPLY_EYEDOT -uniform sampler2D NormalmapTexture; +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; #endif -uniform sampler2D ReflectionTexture; -uniform sampler2D RefractionTexture; -uniform float TextureWidth, TextureHeight; void main(void) { -myhalf3 color; + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); -#ifdef APPLY_DUDV -vec3 displacement = vec3(texture2D(DuDvMapTexture, vec2(TexCoord.pq) * vec2(0.25))); -vec2 coord = vec2(TexCoord.st) + vec2(displacement) * vec2 (0.2); + TransformVerts(Position, Normal, TexCoord); -vec3 fdist = vec3 (normalize(vec3(texture2D(DuDvMapTexture, coord)) - vec3 (0.5))) * vec3(0.005); + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); #else -vec3 fdist = vec3(0.0); + FogGen(Position, v_FogCoord); #endif +#endif // APPLY_FOG -// get projective texcoords -float scale = float(1.0 / float(ProjVector.w)); -float inv2NW = 1.0 / (2.0 * float (TextureWidth)); -float inv2NH = 1.0 / (2.0 * float (TextureHeight)); -vec2 projCoord = (vec2(ProjVector.xy) * scale + vec2 (1.0)) * vec2 (0.5) + vec2(fdist.xy); -projCoord.s = float (clamp (float(projCoord.s), inv2NW, 1.0 - inv2NW)); -projCoord.t = float (clamp (float(projCoord.t), inv2NH, 1.0 - inv2NH)); + qf_FrontColor = vec4(outColor); +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; -myhalf3 refr = myhalf3(0.0); -myhalf3 refl = myhalf3(0.0); + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); -#ifdef APPLY_EYEDOT -// calculate dot product between the surface normal and eye vector -// great for simulating varying water translucency based on the view angle -myhalf3 surfaceNormal = normalize(myhalf3(texture2D(NormalmapTexture, coord)) - myhalf3 (0.5)); -vec3 eyeNormal = normalize(myhalf3(EyeVector)); + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) -float refrdot = float(dot(surfaceNormal, eyeNormal)); -//refrdot = float (clamp (refrdot, 0.0, 1.0)); -float refldot = 1.0 - refrdot; -// get refraction and reflection + v_Position = Position.xyz; -#ifdef APPLY_REFRACTION -refr = (myhalf3(texture2D(RefractionTexture, projCoord))) * refrdot; -#endif -#ifdef APPLY_REFLECTION -refl = (myhalf3(texture2D(ReflectionTexture, projCoord))) * refldot; +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; #endif +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; #else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif -#ifdef APPLY_REFRACTION -refr = (myhalf3(texture2D(RefractionTexture, projCoord))); +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; #endif -#ifdef APPLY_REFLECTION -refl = (myhalf3(texture2D(ReflectionTexture, projCoord))); + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + #endif + +uniform sampler2D u_DepthTexture; + #endif -// add reflection and refraction -#ifdef APPLY_DISTORTION_ALPHA -color = myhalf3(gl_Color.rgb) + myhalf3(mix (refr, refl, float(gl_Color.a))); +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 #else -color = myhalf3(gl_Color.rgb) + refr + refl; + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),1.0); +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); #else -gl_FragColor = vec4(vec3(color),1.0); + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); #endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); } #endif // FRAGMENT_SHADER - diff --git a/shaders/warsow/160.shader_test b/shaders/warsow/160.shader_test new file mode 100644 index 0000000..1afe69a --- /dev/null +++ b/shaders/warsow/160.shader_test @@ -0,0 +1,1431 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 3 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_ENTITY_DECAL +#define APPLY_STRIPES +#define APPLY_CEL_LIGHT +#define APPLY_CEL_LIGHT +#define APPLY_CEL_LIGHT_ADD + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +qf_varying vec3 v_TexCoordCube; + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +uniform mat4 u_ReflectionTexMatrix; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#ifdef APPLY_FOG_COLOR + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); + + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform sampler2D u_BaseTexture; +uniform samplerCube u_CelShadeTexture; + +#ifdef APPLY_DIFFUSE +uniform sampler2D u_DiffuseTexture; +#endif +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif +#ifdef APPLY_STRIPES +uniform sampler2D u_StripesTexture; +#endif +#ifdef APPLY_CEL_LIGHT +uniform samplerCube u_CelLightTexture; +#endif + +void main(void) +{ + myhalf4 inColor = myhalf4(qf_FrontColor); + + myhalf4 tempColor; + + myhalf4 outColor; + outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); + +#ifdef APPLY_ENTITY_DECAL +#ifdef APPLY_ENTITY_DECAL_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_ENTITY_DECAL + +#ifdef APPLY_DIFFUSE + outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord)); +#endif + + outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube)); + +#ifdef APPLY_STRIPES +#ifdef APPLY_STRIPES_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_STRIPES_ADD + +#ifdef APPLY_CEL_LIGHT +#ifdef APPLY_CEL_LIGHT_ADD + outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); +#else + tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_CEL_LIGHT + +#ifdef APPLY_DECAL +#ifdef APPLY_DECAL_ADD + outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_DECAL + + outColor = myhalf4(inColor * outColor); + +#ifdef APPLY_GREYSCALE + outColor.rgb = Greyscale(outColor.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(outColor); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 3 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_ENTITY_DECAL +#define APPLY_STRIPES +#define APPLY_CEL_LIGHT +#define APPLY_CEL_LIGHT +#define APPLY_CEL_LIGHT_ADD + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +qf_varying vec3 v_TexCoordCube; + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +uniform mat4 u_ReflectionTexMatrix; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#ifdef APPLY_FOG_COLOR + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); + + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform sampler2D u_BaseTexture; +uniform samplerCube u_CelShadeTexture; + +#ifdef APPLY_DIFFUSE +uniform sampler2D u_DiffuseTexture; +#endif +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif +#ifdef APPLY_STRIPES +uniform sampler2D u_StripesTexture; +#endif +#ifdef APPLY_CEL_LIGHT +uniform samplerCube u_CelLightTexture; +#endif + +void main(void) +{ + myhalf4 inColor = myhalf4(qf_FrontColor); + + myhalf4 tempColor; + + myhalf4 outColor; + outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); + +#ifdef APPLY_ENTITY_DECAL +#ifdef APPLY_ENTITY_DECAL_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_ENTITY_DECAL + +#ifdef APPLY_DIFFUSE + outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord)); +#endif + + outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube)); + +#ifdef APPLY_STRIPES +#ifdef APPLY_STRIPES_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_STRIPES_ADD + +#ifdef APPLY_CEL_LIGHT +#ifdef APPLY_CEL_LIGHT_ADD + outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); +#else + tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_CEL_LIGHT + +#ifdef APPLY_DECAL +#ifdef APPLY_DECAL_ADD + outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_DECAL + + outColor = myhalf4(inColor * outColor); + +#ifdef APPLY_GREYSCALE + outColor.rgb = Greyscale(outColor.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(outColor); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/163.shader_test b/shaders/warsow/163.shader_test new file mode 100644 index 0000000..dba7913 --- /dev/null +++ b/shaders/warsow/163.shader_test @@ -0,0 +1,2061 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_DLIGHTS 4 +#define NUM_LIGHTMAPS 1 +#define APPLY_SPECULAR +#define APPLY_RELIEFMAPPING + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_DLIGHTS 4 +#define NUM_LIGHTMAPS 1 +#define APPLY_SPECULAR +#define APPLY_RELIEFMAPPING + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/166.shader_test b/shaders/warsow/166.shader_test new file mode 100644 index 0000000..8810c5c --- /dev/null +++ b/shaders/warsow/166.shader_test @@ -0,0 +1,2061 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX +#define NUM_DLIGHTS 4 +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_SPECULAR +#define APPLY_DIRECTIONAL_LIGHT_MIX + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX +#define NUM_DLIGHTS 4 +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_SPECULAR +#define APPLY_DIRECTIONAL_LIGHT_MIX + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/169.shader_test b/shaders/warsow/169.shader_test new file mode 100644 index 0000000..81d4852 --- /dev/null +++ b/shaders/warsow/169.shader_test @@ -0,0 +1,1753 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_TC_GEN_REFLECTION + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_TC_GEN_REFLECTION + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/172.shader_test b/shaders/warsow/172.shader_test new file mode 100644 index 0000000..caf1298 --- /dev/null +++ b/shaders/warsow/172.shader_test @@ -0,0 +1,1753 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_TC_GEN_ENV + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_TC_GEN_ENV + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/175.shader_test b/shaders/warsow/175.shader_test new file mode 100644 index 0000000..5194082 --- /dev/null +++ b/shaders/warsow/175.shader_test @@ -0,0 +1,1755 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_RGB_DISTANCERAMP +#define APPLY_ALPHA_CONST +#define APPLY_TC_GEN_ENV + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_RGB_DISTANCERAMP +#define APPLY_ALPHA_CONST +#define APPLY_TC_GEN_ENV + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/178.shader_test b/shaders/warsow/178.shader_test new file mode 100644 index 0000000..723cd6a --- /dev/null +++ b/shaders/warsow/178.shader_test @@ -0,0 +1,2059 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_DLIGHTS 8 +#define NUM_LIGHTMAPS 1 +#define APPLY_RELIEFMAPPING + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_DLIGHTS 8 +#define NUM_LIGHTMAPS 1 +#define APPLY_RELIEFMAPPING + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/181.shader_test b/shaders/warsow/181.shader_test new file mode 100644 index 0000000..d0ab50b --- /dev/null +++ b/shaders/warsow/181.shader_test @@ -0,0 +1,2059 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_DLIGHTS 8 +#define NUM_LIGHTMAPS 1 +#define APPLY_SPECULAR + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_DLIGHTS 8 +#define NUM_LIGHTMAPS 1 +#define APPLY_SPECULAR + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/184.shader_test b/shaders/warsow/184.shader_test new file mode 100644 index 0000000..ef4c4a0 --- /dev/null +++ b/shaders/warsow/184.shader_test @@ -0,0 +1,2057 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_DLIGHTS 8 +#define NUM_LIGHTMAPS 1 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_DLIGHTS 8 +#define NUM_LIGHTMAPS 1 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/187.shader_test b/shaders/warsow/187.shader_test new file mode 100644 index 0000000..480a43a --- /dev/null +++ b/shaders/warsow/187.shader_test @@ -0,0 +1,1751 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_VERTEX + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_VERTEX + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/19.shader_test b/shaders/warsow/19.shader_test index 9b644bc..26aac1d 100644 --- a/shaders/warsow/19.shader_test +++ b/shaders/warsow/19.shader_test @@ -1,225 +1,1415 @@ [require] GLSL >= 1.10 -[fragment shader] -#define FRAGMENT_SHADER -// Warsow GLSL shader - -#if !defined(__GLSL_CG_DATA_TYPES) +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 #endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} -varying vec4 ProjVector; +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -void main(void) +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif { -gl_FrontColor = gl_Color; +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -mat4 textureMatrix; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; -textureMatrix = gl_TextureMatrix[0]; +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -gl_Position = ftransform(); -ProjVector = textureMatrix * gl_Vertex; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} } -#endif // VERTEX_SHADER +float len = length(DQReal); +DQReal /= len; +DQDual /= len; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; -#ifdef FRAGMENT_SHADER -// Fragment shader +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) -uniform myhalf3 LightAmbient; -uniform float TextureWidth, TextureHeight; -uniform float ProjDistance; -uniform sampler2DShadow ShadowmapTexture; +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +qf_varying vec3 v_TexCoordCube; + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +uniform mat4 u_ReflectionTexMatrix; void main(void) { -myhalf color = myhalf(1.0); + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); -if (ProjVector.w <= 0.0 || ProjVector.w >= ProjDistance) -discard; +#ifdef APPLY_FOG +#ifdef APPLY_FOG_COLOR + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif -float dtW = 1.0 / TextureWidth; -float dtH = 1.0 / TextureHeight; + qf_FrontColor = vec4(outColor); -vec3 coord = vec3 (ProjVector.xyz / ProjVector.w); -coord = (coord + vec3 (1.0)) * vec3 (0.5); -coord.s = float (clamp (float(coord.s), dtW, 1.0 - dtW)); -coord.t = float (clamp (float(coord.t), dtH, 1.0 - dtH)); -coord.r = float (clamp (float(coord.r), 0.0, 1.0)); + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); -myhalf shadow0 = myhalf(shadow2D(ShadowmapTexture, coord).r); -myhalf shadow = shadow0; + gl_Position = u_ModelViewProjectionMatrix * Position; +} -#if defined(APPLY_PCF2x2) || defined(APPLY_PCF3x3) +#endif // VERTEX_SHADER -vec3 coord2 = coord + vec3(0.0, dtH, 0.0); -myhalf shadow1 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +#ifdef FRAGMENT_SHADER +// Fragment shader -coord2 = coord + vec3(dtW, dtH, 0.0); -myhalf shadow2 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +uniform sampler2D u_BaseTexture; +uniform samplerCube u_CelShadeTexture; -coord2 = coord + vec3(dtW, 0.0, 0.0); -myhalf shadow3 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +#ifdef APPLY_DIFFUSE +uniform sampler2D u_DiffuseTexture; +#endif +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif +#ifdef APPLY_STRIPES +uniform sampler2D u_StripesTexture; +#endif +#ifdef APPLY_CEL_LIGHT +uniform samplerCube u_CelLightTexture; +#endif -#if defined(APPLY_PCF3x3) -coord2 = coord + vec3(-dtW, 0.0, 0.0); -myhalf shadow4 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +void main(void) +{ + myhalf4 inColor = myhalf4(qf_FrontColor); -coord2 = coord + vec3(-dtW, -dtH, 0.0); -myhalf shadow5 = myhalf (shadow2D (ShadowmapTexture, coord2).r); + myhalf4 tempColor; -coord2 = coord + vec3(0.0, -dtH, 0.0); -myhalf shadow6 = myhalf (shadow2D (ShadowmapTexture, coord2).r); + myhalf4 outColor; + outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); -coord2 = coord + vec3(dtW, -dtH, 0.0); -myhalf shadow7 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +#ifdef APPLY_ENTITY_DECAL +#ifdef APPLY_ENTITY_DECAL_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_ENTITY_DECAL + +#ifdef APPLY_DIFFUSE + outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord)); +#endif -coord2 = coord + vec3(-dtW, dtH, 0.0); -myhalf shadow8 = myhalf (shadow2D (ShadowmapTexture, coord2).r); + outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube)); -shadow = (shadow0 + shadow1 + shadow2 + shadow3 + shadow4 + shadow5 + shadow6 + shadow7 + shadow8) * myhalf(0.11); +#ifdef APPLY_STRIPES +#ifdef APPLY_STRIPES_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord)); #else -shadow = (shadow0 + shadow1 + shadow2 + shadow3) * myhalf(0.25); + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); #endif +#endif // APPLY_STRIPES_ADD + +#ifdef APPLY_CEL_LIGHT +#ifdef APPLY_CEL_LIGHT_ADD + outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); #else -shadow = shadow0; + tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); #endif +#endif // APPLY_CEL_LIGHT -float attenuation = float (ProjVector.w) / ProjDistance; -myhalf compensation = myhalf(0.25) - max(LightAmbient.x, max(LightAmbient.y, LightAmbient.z)) -;compensation = max (compensation, 0.0); -color = shadow + attenuation + compensation; +#ifdef APPLY_DECAL +#ifdef APPLY_DECAL_ADD + outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_DECAL -gl_FragColor = vec4(vec3(color),1.0); + outColor = myhalf4(inColor * outColor); + +#ifdef APPLY_GREYSCALE + outColor.rgb = Greyscale(outColor.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(outColor); } #endif // FRAGMENT_SHADER +[fragment shader] +#version 130 -[vertex shader] -#define VERTEX_SHADER -// Warsow GLSL shader - -#if !defined(__GLSL_CG_DATA_TYPES) +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -varying vec4 ProjVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -void main(void) +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif { -gl_FrontColor = gl_Color; +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -mat4 textureMatrix; +vec4 DQReal1, DQDual1; +float scale; -textureMatrix = gl_TextureMatrix[0]; +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -gl_Position = ftransform(); -ProjVector = textureMatrix * gl_Vertex; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} } -#endif // VERTEX_SHADER +float len = length(DQReal); +DQReal /= len; +DQDual /= len; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) -#ifdef FRAGMENT_SHADER -// Fragment shader -uniform myhalf3 LightAmbient; +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; -uniform float TextureWidth, TextureHeight; -uniform float ProjDistance; -uniform sampler2DShadow ShadowmapTexture; +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +qf_varying vec3 v_TexCoordCube; + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +uniform mat4 u_ReflectionTexMatrix; void main(void) { -myhalf color = myhalf(1.0); + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); -if (ProjVector.w <= 0.0 || ProjVector.w >= ProjDistance) -discard; + TransformVerts(Position, Normal, TexCoord); -float dtW = 1.0 / TextureWidth; -float dtH = 1.0 / TextureHeight; + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); -vec3 coord = vec3 (ProjVector.xyz / ProjVector.w); -coord = (coord + vec3 (1.0)) * vec3 (0.5); -coord.s = float (clamp (float(coord.s), dtW, 1.0 - dtW)); -coord.t = float (clamp (float(coord.t), dtH, 1.0 - dtH)); -coord.r = float (clamp (float(coord.r), 0.0, 1.0)); +#ifdef APPLY_FOG +#ifdef APPLY_FOG_COLOR + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif -myhalf shadow0 = myhalf(shadow2D(ShadowmapTexture, coord).r); -myhalf shadow = shadow0; + qf_FrontColor = vec4(outColor); -#if defined(APPLY_PCF2x2) || defined(APPLY_PCF3x3) + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); -vec3 coord2 = coord + vec3(0.0, dtH, 0.0); -myhalf shadow1 = myhalf (shadow2D (ShadowmapTexture, coord2).r); + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform sampler2D u_BaseTexture; +uniform samplerCube u_CelShadeTexture; + +#ifdef APPLY_DIFFUSE +uniform sampler2D u_DiffuseTexture; +#endif +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif +#ifdef APPLY_STRIPES +uniform sampler2D u_StripesTexture; +#endif +#ifdef APPLY_CEL_LIGHT +uniform samplerCube u_CelLightTexture; +#endif -coord2 = coord + vec3(dtW, dtH, 0.0); -myhalf shadow2 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +void main(void) +{ + myhalf4 inColor = myhalf4(qf_FrontColor); -coord2 = coord + vec3(dtW, 0.0, 0.0); -myhalf shadow3 = myhalf (shadow2D (ShadowmapTexture, coord2).r); + myhalf4 tempColor; -#if defined(APPLY_PCF3x3) -coord2 = coord + vec3(-dtW, 0.0, 0.0); -myhalf shadow4 = myhalf (shadow2D (ShadowmapTexture, coord2).r); + myhalf4 outColor; + outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); -coord2 = coord + vec3(-dtW, -dtH, 0.0); -myhalf shadow5 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +#ifdef APPLY_ENTITY_DECAL +#ifdef APPLY_ENTITY_DECAL_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_ENTITY_DECAL -coord2 = coord + vec3(0.0, -dtH, 0.0); -myhalf shadow6 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +#ifdef APPLY_DIFFUSE + outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord)); +#endif -coord2 = coord + vec3(dtW, -dtH, 0.0); -myhalf shadow7 = myhalf (shadow2D (ShadowmapTexture, coord2).r); + outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube)); -coord2 = coord + vec3(-dtW, dtH, 0.0); -myhalf shadow8 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +#ifdef APPLY_STRIPES +#ifdef APPLY_STRIPES_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_STRIPES_ADD -shadow = (shadow0 + shadow1 + shadow2 + shadow3 + shadow4 + shadow5 + shadow6 + shadow7 + shadow8) * myhalf(0.11); +#ifdef APPLY_CEL_LIGHT +#ifdef APPLY_CEL_LIGHT_ADD + outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); #else -shadow = (shadow0 + shadow1 + shadow2 + shadow3) * myhalf(0.25); + tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); #endif +#endif // APPLY_CEL_LIGHT + +#ifdef APPLY_DECAL +#ifdef APPLY_DECAL_ADD + outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); #else -shadow = shadow0; + tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_DECAL + + outColor = myhalf4(inColor * outColor); + +#ifdef APPLY_GREYSCALE + outColor.rgb = Greyscale(outColor.rgb); #endif -float attenuation = float (ProjVector.w) / ProjDistance; -myhalf compensation = myhalf(0.25) - max(LightAmbient.x, max(LightAmbient.y, LightAmbient.z)) -;compensation = max (compensation, 0.0); -color = shadow + attenuation + compensation; +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity); +#endif -gl_FragColor = vec4(vec3(color),1.0); + qf_FragColor = vec4(outColor); } #endif // FRAGMENT_SHADER - diff --git a/shaders/warsow/190.shader_test b/shaders/warsow/190.shader_test new file mode 100644 index 0000000..01fad34 --- /dev/null +++ b/shaders/warsow/190.shader_test @@ -0,0 +1,2061 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_DLIGHTS 8 +#define NUM_LIGHTMAPS 1 +#define APPLY_SPECULAR +#define APPLY_RELIEFMAPPING + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_DLIGHTS 8 +#define NUM_LIGHTMAPS 1 +#define APPLY_SPECULAR +#define APPLY_RELIEFMAPPING + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/193.shader_test b/shaders/warsow/193.shader_test new file mode 100644 index 0000000..5b5950a --- /dev/null +++ b/shaders/warsow/193.shader_test @@ -0,0 +1,1753 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX +#define NUM_DLIGHTS 4 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX +#define NUM_DLIGHTS 4 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/196.shader_test b/shaders/warsow/196.shader_test new file mode 100644 index 0000000..86d5cfd --- /dev/null +++ b/shaders/warsow/196.shader_test @@ -0,0 +1,1675 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_PCF +#define NUM_SHADOWS 4 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) +#endif + + +#ifndef NUM_SHADOWS +#define NUM_SHADOWS 1 +#endif + +qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS]; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS]; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + + for (int i = 0; i < NUM_SHADOWS; i++) + { + v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position; + // a trick whish allows us not to perform the + // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)' + // computation in the fragment shader + v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5; + } +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_RGB_SHADOW +uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy))) +#else +uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) float(qf_shadow(t,v)) +#endif + +uniform float u_ShadowAlpha; +uniform float u_ShadowProjDistance[NUM_SHADOWS]; +uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS]; + +void main(void) +{ + float finalcolor = 1.0; + +#if NUM_SHADOWS >= 1 +#define SHADOW_INDEX 0 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 2 +#define SHADOW_INDEX 1 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 3 +#define SHADOW_INDEX 2 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 4 +#define SHADOW_INDEX 3 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + + qf_FragColor = vec4(vec3(finalcolor),1.0); +} + +#endif // FRAGMENT_SHADER + + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_PCF +#define NUM_SHADOWS 4 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) +#endif + + +#ifndef NUM_SHADOWS +#define NUM_SHADOWS 1 +#endif + +qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS]; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS]; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + + for (int i = 0; i < NUM_SHADOWS; i++) + { + v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position; + // a trick whish allows us not to perform the + // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)' + // computation in the fragment shader + v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5; + } +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_RGB_SHADOW +uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy))) +#else +uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) float(qf_shadow(t,v)) +#endif + +uniform float u_ShadowAlpha; +uniform float u_ShadowProjDistance[NUM_SHADOWS]; +uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS]; + +void main(void) +{ + float finalcolor = 1.0; + +#if NUM_SHADOWS >= 1 +#define SHADOW_INDEX 0 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 2 +#define SHADOW_INDEX 1 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 3 +#define SHADOW_INDEX 2 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 4 +#define SHADOW_INDEX 3 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + + qf_FragColor = vec4(vec3(finalcolor),1.0); +} + +#endif // FRAGMENT_SHADER + + diff --git a/shaders/warsow/199.shader_test b/shaders/warsow/199.shader_test new file mode 100644 index 0000000..9c86962 --- /dev/null +++ b/shaders/warsow/199.shader_test @@ -0,0 +1,1241 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 4 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +uniform float u_OutlineHeight; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + Position += vec4(Normal * u_OutlineHeight, 0.0); + gl_Position = u_ModelViewProjectionMatrix * Position; + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG + myhalf4 tempColor = myhalf4(1.0); + FogGen(Position, tempColor, myhalf2(0.0, 1.0)); + outColor.rgb = mix(u_Fog.Color, outColor.rgb, tempColor.a); +#endif + + qf_FrontColor = vec4(outColor); +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform float u_OutlineCutOff; + +void main(void) +{ +#ifdef APPLY_OUTLINES_CUTOFF + if (u_OutlineCutOff > 0.0 && (gl_FragCoord.z / gl_FragCoord.w > u_OutlineCutOff)) + discard; +#endif + qf_FragColor = vec4(qf_FrontColor); +} + +#endif // FRAGMENT_SHADER + + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 4 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +uniform float u_OutlineHeight; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + Position += vec4(Normal * u_OutlineHeight, 0.0); + gl_Position = u_ModelViewProjectionMatrix * Position; + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG + myhalf4 tempColor = myhalf4(1.0); + FogGen(Position, tempColor, myhalf2(0.0, 1.0)); + outColor.rgb = mix(u_Fog.Color, outColor.rgb, tempColor.a); +#endif + + qf_FrontColor = vec4(outColor); +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform float u_OutlineCutOff; + +void main(void) +{ +#ifdef APPLY_OUTLINES_CUTOFF + if (u_OutlineCutOff > 0.0 && (gl_FragCoord.z / gl_FragCoord.w > u_OutlineCutOff)) + discard; +#endif + qf_FragColor = vec4(qf_FrontColor); +} + +#endif // FRAGMENT_SHADER + + diff --git a/shaders/warsow/202.shader_test b/shaders/warsow/202.shader_test new file mode 100644 index 0000000..7700177 --- /dev/null +++ b/shaders/warsow/202.shader_test @@ -0,0 +1,1755 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_DLIGHTS 4 +#define NUM_LIGHTMAPS 1 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_DLIGHTS 4 +#define NUM_LIGHTMAPS 1 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/205.shader_test b/shaders/warsow/205.shader_test new file mode 100644 index 0000000..37d0f14 --- /dev/null +++ b/shaders/warsow/205.shader_test @@ -0,0 +1,2084 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_LIGHTMAPS 1 +#define APPLY_SPECULAR +#define APPLY_RELIEFMAPPING +#define APPLY_DEFORMVERTS + +#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpritePoint; +#else +#define a_SpritePoint vec4(0.0) +#endif + +#if defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpriteRightUpAxis; +#else +#define a_SpriteRightUpAxis vec4(0.0) +#endif + +void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +float t = 0.0; +vec3 dist; +vec3 right, up, forward, newright; + +#if defined(WAVE_SIN) +t = sin(TexCoord.s * 4.000000 + u_QF_ShaderTime * -1.500000); +Position.xyz += max (-1.0 + 1.000000, t) * 7.000000 * Normal.xyz; +#endif +} + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_LIGHTMAPS 1 +#define APPLY_SPECULAR +#define APPLY_RELIEFMAPPING + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/208.shader_test b/shaders/warsow/208.shader_test new file mode 100644 index 0000000..ea7b0d1 --- /dev/null +++ b/shaders/warsow/208.shader_test @@ -0,0 +1,1698 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_PCF +#define APPLY_DEFORMVERTS + +#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpritePoint; +#else +#define a_SpritePoint vec4(0.0) +#endif + +#if defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpriteRightUpAxis; +#else +#define a_SpriteRightUpAxis vec4(0.0) +#endif + +void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +float t = 0.0; +vec3 dist; +vec3 right, up, forward, newright; + +#if defined(WAVE_SIN) +t = sin(TexCoord.s * 4.000000 + u_QF_ShaderTime * -1.500000); +Position.xyz += max (-1.0 + 1.000000, t) * 7.000000 * Normal.xyz; +#endif +} + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) +#endif + + +#ifndef NUM_SHADOWS +#define NUM_SHADOWS 1 +#endif + +qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS]; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS]; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + + for (int i = 0; i < NUM_SHADOWS; i++) + { + v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position; + // a trick whish allows us not to perform the + // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)' + // computation in the fragment shader + v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5; + } +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_RGB_SHADOW +uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy))) +#else +uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) float(qf_shadow(t,v)) +#endif + +uniform float u_ShadowAlpha; +uniform float u_ShadowProjDistance[NUM_SHADOWS]; +uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS]; + +void main(void) +{ + float finalcolor = 1.0; + +#if NUM_SHADOWS >= 1 +#define SHADOW_INDEX 0 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 2 +#define SHADOW_INDEX 1 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 3 +#define SHADOW_INDEX 2 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 4 +#define SHADOW_INDEX 3 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + + qf_FragColor = vec4(vec3(finalcolor),1.0); +} + +#endif // FRAGMENT_SHADER + + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_PCF + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) +#endif + + +#ifndef NUM_SHADOWS +#define NUM_SHADOWS 1 +#endif + +qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS]; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS]; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + + for (int i = 0; i < NUM_SHADOWS; i++) + { + v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position; + // a trick whish allows us not to perform the + // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)' + // computation in the fragment shader + v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5; + } +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_RGB_SHADOW +uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy))) +#else +uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) float(qf_shadow(t,v)) +#endif + +uniform float u_ShadowAlpha; +uniform float u_ShadowProjDistance[NUM_SHADOWS]; +uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS]; + +void main(void) +{ + float finalcolor = 1.0; + +#if NUM_SHADOWS >= 1 +#define SHADOW_INDEX 0 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 2 +#define SHADOW_INDEX 1 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 3 +#define SHADOW_INDEX 2 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 4 +#define SHADOW_INDEX 3 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + + qf_FragColor = vec4(vec3(finalcolor),1.0); +} + +#endif // FRAGMENT_SHADER + + diff --git a/shaders/warsow/211.shader_test b/shaders/warsow/211.shader_test new file mode 100644 index 0000000..ed510d6 --- /dev/null +++ b/shaders/warsow/211.shader_test @@ -0,0 +1,1793 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_AUTOSPRITE2 +#define APPLY_DEFORMVERTS + +#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpritePoint; +#else +#define a_SpritePoint vec4(0.0) +#endif + +#if defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpriteRightUpAxis; +#else +#define a_SpriteRightUpAxis vec4(0.0) +#endif + +void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +float t = 0.0; +vec3 dist; +vec3 right, up, forward, newright; + +#if defined(WAVE_SIN) +// local sprite axes +right = QF_LatLong2Norm(a_SpriteRightUpAxis.xy) * u_QF_MirrorSide; +up = QF_LatLong2Norm(a_SpriteRightUpAxis.zw); + +// mid of quad to camera vector +dist = u_QF_ViewOrigin - u_QF_EntityOrigin - a_SpritePoint.xyz; + +// filter any longest-axis-parts off the camera-direction +forward = normalize(dist - up * dot(dist, up)); + +// the right axis vector as it should be to face the camera +newright = cross(up, forward); + +// rotate the quad vertex around the up axis vector +t = dot(right, Position.xyz - a_SpritePoint.xyz); +Position.xyz += t * (newright - right); +Normal.xyz = forward; +#endif +} + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_AUTOSPRITE2 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/214.shader_test b/shaders/warsow/214.shader_test new file mode 100644 index 0000000..e538a2f --- /dev/null +++ b/shaders/warsow/214.shader_test @@ -0,0 +1,1784 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_RGB_DISTANCERAMP +#define APPLY_ALPHA_CONST +#define APPLY_AUTOSPRITE +#define APPLY_DEFORMVERTS + +#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpritePoint; +#else +#define a_SpritePoint vec4(0.0) +#endif + +#if defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpriteRightUpAxis; +#else +#define a_SpriteRightUpAxis vec4(0.0) +#endif + +void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +float t = 0.0; +vec3 dist; +vec3 right, up, forward, newright; + +#if defined(WAVE_SIN) +right = (1.0 - step(0.5, TexCoord.s) * 2.0) * u_QF_ViewAxis[1] * u_QF_MirrorSide; +;up = (1.0 - step(0.5, TexCoord.t) * 2.0) * u_QF_ViewAxis[2]; +forward = -1.0 * u_QF_ViewAxis[0]; +Position.xyz = a_SpritePoint.xyz + (right + up) * a_SpritePoint.w; +Normal.xyz = forward; +TexCoord.st = vec2(step(0.5, TexCoord.s),step(0.5, TexCoord.t)); +#endif +} + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_RGB_DISTANCERAMP +#define APPLY_ALPHA_CONST +#define APPLY_AUTOSPRITE + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/217.shader_test b/shaders/warsow/217.shader_test new file mode 100644 index 0000000..7114b78 --- /dev/null +++ b/shaders/warsow/217.shader_test @@ -0,0 +1,1782 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_AUTOSPRITE +#define APPLY_DEFORMVERTS + +#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpritePoint; +#else +#define a_SpritePoint vec4(0.0) +#endif + +#if defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpriteRightUpAxis; +#else +#define a_SpriteRightUpAxis vec4(0.0) +#endif + +void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +float t = 0.0; +vec3 dist; +vec3 right, up, forward, newright; + +#if defined(WAVE_SIN) +right = (1.0 - step(0.5, TexCoord.s) * 2.0) * u_QF_ViewAxis[1] * u_QF_MirrorSide; +;up = (1.0 - step(0.5, TexCoord.t) * 2.0) * u_QF_ViewAxis[2]; +forward = -1.0 * u_QF_ViewAxis[0]; +Position.xyz = a_SpritePoint.xyz + (right + up) * a_SpritePoint.w; +Normal.xyz = forward; +TexCoord.st = vec2(step(0.5, TexCoord.s),step(0.5, TexCoord.t)); +#endif +} + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_AUTOSPRITE + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/22.shader_test b/shaders/warsow/22.shader_test index b4f6f7c..ced0b98 100644 --- a/shaders/warsow/22.shader_test +++ b/shaders/warsow/22.shader_test @@ -1,101 +1,1107 @@ [require] GLSL >= 1.10 -[fragment shader] -#define FRAGMENT_SHADER -// Warsow GLSL shader +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} -varying vec4 ProjVector; +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform float OutlineHeight; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -void main(void) +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; -vec4 n = vec4(gl_Normal.xyz, 0.0); -vec4 v = vec4(gl_Vertex) + n * OutlineHeight; +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -gl_Position = gl_ModelViewProjectionMatrix * v; -ProjVector = gl_Position; -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * v; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif } -#endif // VERTEX_SHADER +// use defines to overload the transform function +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#ifdef FRAGMENT_SHADER -// Fragment shader +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -uniform float OutlineCutOff; +vec4 DQReal1, DQDual1; +float scale; -void main(void) +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) { +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_OUTLINES_CUTOFF -if (OutlineCutOff > 0.0 && (ProjVector.w > OutlineCutOff)) -discard; +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -gl_FragColor = vec4 (gl_Color); +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif } -#endif // FRAGMENT_SHADER +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -[vertex shader] -#define VERTEX_SHADER -// Warsow GLSL shader +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -varying vec4 ProjVector; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} +#endif #ifdef VERTEX_SHADER -// Vertex shader +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) -uniform float OutlineHeight; +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -void main(void) +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +struct Fog { -gl_FrontColor = gl_Color; + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; -vec4 n = vec4(gl_Normal.xyz, 0.0); -vec4 v = vec4(gl_Vertex) + n * OutlineHeight; +uniform Fog u_Fog; -gl_Position = gl_ModelViewProjectionMatrix * v; -ProjVector = gl_Position; -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * v; +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +qf_varying vec2 v_FogCoord; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif } -#endif // VERTEX_SHADER +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + FogGen(Position, v_FogCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER #ifdef FRAGMENT_SHADER // Fragment shader -uniform float OutlineCutOff; - void main(void) { + float fogDensity = FogDensity(v_FogCoord); + qf_FragColor = vec4(u_Fog.Color, fogDensity); +} + +#endif // FRAGMENT_SHADER -#ifdef APPLY_OUTLINES_CUTOFF -if (OutlineCutOff > 0.0 && (ProjVector.w > OutlineCutOff)) -discard; + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif #endif -gl_FragColor = vec4 (gl_Color); +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +qf_varying vec2 v_FogCoord; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + FogGen(Position, v_FogCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +void main(void) +{ + float fogDensity = FogDensity(v_FogCoord); + qf_FragColor = vec4(u_Fog.Color, fogDensity); } #endif // FRAGMENT_SHADER diff --git a/shaders/warsow/220.shader_test b/shaders/warsow/220.shader_test new file mode 100644 index 0000000..3817587 --- /dev/null +++ b/shaders/warsow/220.shader_test @@ -0,0 +1,1784 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_CONST +#define APPLY_ALPHA_DISTANCERAMP +#define APPLY_AUTOSPRITE +#define APPLY_DEFORMVERTS + +#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpritePoint; +#else +#define a_SpritePoint vec4(0.0) +#endif + +#if defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpriteRightUpAxis; +#else +#define a_SpriteRightUpAxis vec4(0.0) +#endif + +void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +float t = 0.0; +vec3 dist; +vec3 right, up, forward, newright; + +#if defined(WAVE_SIN) +right = (1.0 - step(0.5, TexCoord.s) * 2.0) * u_QF_ViewAxis[1] * u_QF_MirrorSide; +;up = (1.0 - step(0.5, TexCoord.t) * 2.0) * u_QF_ViewAxis[2]; +forward = -1.0 * u_QF_ViewAxis[0]; +Position.xyz = a_SpritePoint.xyz + (right + up) * a_SpritePoint.w; +Normal.xyz = forward; +TexCoord.st = vec2(step(0.5, TexCoord.s),step(0.5, TexCoord.t)); +#endif +} + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_CONST +#define APPLY_ALPHA_DISTANCERAMP +#define APPLY_AUTOSPRITE + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/223.shader_test b/shaders/warsow/223.shader_test new file mode 100644 index 0000000..9b48bba --- /dev/null +++ b/shaders/warsow/223.shader_test @@ -0,0 +1,1797 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_RGB_DISTANCERAMP +#define APPLY_ALPHA_CONST +#define APPLY_AUTOSPRITE2 +#define APPLY_SOFT_PARTICLE +#define APPLY_DEFORMVERTS + +#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpritePoint; +#else +#define a_SpritePoint vec4(0.0) +#endif + +#if defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpriteRightUpAxis; +#else +#define a_SpriteRightUpAxis vec4(0.0) +#endif + +void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +float t = 0.0; +vec3 dist; +vec3 right, up, forward, newright; + +#if defined(WAVE_SIN) +// local sprite axes +right = QF_LatLong2Norm(a_SpriteRightUpAxis.xy) * u_QF_MirrorSide; +up = QF_LatLong2Norm(a_SpriteRightUpAxis.zw); + +// mid of quad to camera vector +dist = u_QF_ViewOrigin - u_QF_EntityOrigin - a_SpritePoint.xyz; + +// filter any longest-axis-parts off the camera-direction +forward = normalize(dist - up * dot(dist, up)); + +// the right axis vector as it should be to face the camera +newright = cross(up, forward); + +// rotate the quad vertex around the up axis vector +t = dot(right, Position.xyz - a_SpritePoint.xyz); +Position.xyz += t * (newright - right); +Normal.xyz = forward; +#endif +} + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_RGB_DISTANCERAMP +#define APPLY_ALPHA_CONST +#define APPLY_AUTOSPRITE2 +#define APPLY_SOFT_PARTICLE + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/226.shader_test b/shaders/warsow/226.shader_test new file mode 100644 index 0000000..0e5f99e --- /dev/null +++ b/shaders/warsow/226.shader_test @@ -0,0 +1,1784 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX +#define APPLY_AUTOSPRITE +#define APPLY_DEFORMVERTS + +#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpritePoint; +#else +#define a_SpritePoint vec4(0.0) +#endif + +#if defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpriteRightUpAxis; +#else +#define a_SpriteRightUpAxis vec4(0.0) +#endif + +void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +float t = 0.0; +vec3 dist; +vec3 right, up, forward, newright; + +#if defined(WAVE_SIN) +right = (1.0 - TexCoord.s * 2.0) * u_QF_ViewAxis[1] * u_QF_MirrorSide; +;up = (1.0 - TexCoord.t * 2.0) * u_QF_ViewAxis[2]; +forward = -1.0 * u_QF_ViewAxis[0]; +// prevent the particle from disappearing at large distances +t = dot(a_SpritePoint.xyz + u_QF_EntityOrigin - u_QF_ViewOrigin, u_QF_ViewAxis[0]); +t = 1.5 + step(20.0, t) * t * 0.006; +Position.xyz = a_SpritePoint.xyz + (right + up) * t * a_SpritePoint.w; +Normal.xyz = forward; +#endif +} + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX +#define APPLY_AUTOSPRITE + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/229.shader_test b/shaders/warsow/229.shader_test new file mode 100644 index 0000000..12a6a93 --- /dev/null +++ b/shaders/warsow/229.shader_test @@ -0,0 +1,1795 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_RGB_DISTANCERAMP +#define APPLY_ALPHA_CONST +#define APPLY_AUTOSPRITE2 +#define APPLY_DEFORMVERTS + +#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpritePoint; +#else +#define a_SpritePoint vec4(0.0) +#endif + +#if defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpriteRightUpAxis; +#else +#define a_SpriteRightUpAxis vec4(0.0) +#endif + +void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +float t = 0.0; +vec3 dist; +vec3 right, up, forward, newright; + +#if defined(WAVE_SIN) +// local sprite axes +right = QF_LatLong2Norm(a_SpriteRightUpAxis.xy) * u_QF_MirrorSide; +up = QF_LatLong2Norm(a_SpriteRightUpAxis.zw); + +// mid of quad to camera vector +dist = u_QF_ViewOrigin - u_QF_EntityOrigin - a_SpritePoint.xyz; + +// filter any longest-axis-parts off the camera-direction +forward = normalize(dist - up * dot(dist, up)); + +// the right axis vector as it should be to face the camera +newright = cross(up, forward); + +// rotate the quad vertex around the up axis vector +t = dot(right, Position.xyz - a_SpritePoint.xyz); +Position.xyz += t * (newright - right); +Normal.xyz = forward; +#endif +} + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_RGB_DISTANCERAMP +#define APPLY_ALPHA_CONST +#define APPLY_AUTOSPRITE2 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/232.shader_test b/shaders/warsow/232.shader_test new file mode 100644 index 0000000..f4179af --- /dev/null +++ b/shaders/warsow/232.shader_test @@ -0,0 +1,1784 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_AUTOSPRITE +#define APPLY_DEFORMVERTS + +#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpritePoint; +#else +#define a_SpritePoint vec4(0.0) +#endif + +#if defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpriteRightUpAxis; +#else +#define a_SpriteRightUpAxis vec4(0.0) +#endif + +void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +float t = 0.0; +vec3 dist; +vec3 right, up, forward, newright; + +#if defined(WAVE_SIN) +right = (1.0 - TexCoord.s * 2.0) * u_QF_ViewAxis[1] * u_QF_MirrorSide; +;up = (1.0 - TexCoord.t * 2.0) * u_QF_ViewAxis[2]; +forward = -1.0 * u_QF_ViewAxis[0]; +// prevent the particle from disappearing at large distances +t = dot(a_SpritePoint.xyz + u_QF_EntityOrigin - u_QF_ViewOrigin, u_QF_ViewAxis[0]); +t = 1.5 + step(20.0, t) * t * 0.006; +Position.xyz = a_SpritePoint.xyz + (right + up) * t * a_SpritePoint.w; +Normal.xyz = forward; +#endif +} + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_AUTOSPRITE + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/235.shader_test b/shaders/warsow/235.shader_test new file mode 100644 index 0000000..88557ad --- /dev/null +++ b/shaders/warsow/235.shader_test @@ -0,0 +1,2063 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX +#define NUM_DLIGHTS 4 +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_SPECULAR +#define APPLY_RELIEFMAPPING +#define APPLY_DIRECTIONAL_LIGHT_MIX + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX +#define NUM_DLIGHTS 4 +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_SPECULAR +#define APPLY_RELIEFMAPPING +#define APPLY_DIRECTIONAL_LIGHT_MIX + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/238.shader_test b/shaders/warsow/238.shader_test new file mode 100644 index 0000000..ebe45c8 --- /dev/null +++ b/shaders/warsow/238.shader_test @@ -0,0 +1,2059 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX +#define NUM_DLIGHTS 4 +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_DIRECTIONAL_LIGHT_MIX + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX +#define NUM_DLIGHTS 4 +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_DIRECTIONAL_LIGHT_MIX + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/241.shader_test b/shaders/warsow/241.shader_test new file mode 100644 index 0000000..b1f3a91 --- /dev/null +++ b/shaders/warsow/241.shader_test @@ -0,0 +1,1421 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 4 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +qf_varying vec3 v_TexCoordCube; + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +uniform mat4 u_ReflectionTexMatrix; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#ifdef APPLY_FOG_COLOR + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); + + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform sampler2D u_BaseTexture; +uniform samplerCube u_CelShadeTexture; + +#ifdef APPLY_DIFFUSE +uniform sampler2D u_DiffuseTexture; +#endif +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif +#ifdef APPLY_STRIPES +uniform sampler2D u_StripesTexture; +#endif +#ifdef APPLY_CEL_LIGHT +uniform samplerCube u_CelLightTexture; +#endif + +void main(void) +{ + myhalf4 inColor = myhalf4(qf_FrontColor); + + myhalf4 tempColor; + + myhalf4 outColor; + outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); + +#ifdef APPLY_ENTITY_DECAL +#ifdef APPLY_ENTITY_DECAL_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_ENTITY_DECAL + +#ifdef APPLY_DIFFUSE + outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord)); +#endif + + outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube)); + +#ifdef APPLY_STRIPES +#ifdef APPLY_STRIPES_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_STRIPES_ADD + +#ifdef APPLY_CEL_LIGHT +#ifdef APPLY_CEL_LIGHT_ADD + outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); +#else + tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_CEL_LIGHT + +#ifdef APPLY_DECAL +#ifdef APPLY_DECAL_ADD + outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_DECAL + + outColor = myhalf4(inColor * outColor); + +#ifdef APPLY_GREYSCALE + outColor.rgb = Greyscale(outColor.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(outColor); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 4 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +qf_varying vec3 v_TexCoordCube; + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +uniform mat4 u_ReflectionTexMatrix; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#ifdef APPLY_FOG_COLOR + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); + + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform sampler2D u_BaseTexture; +uniform samplerCube u_CelShadeTexture; + +#ifdef APPLY_DIFFUSE +uniform sampler2D u_DiffuseTexture; +#endif +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif +#ifdef APPLY_STRIPES +uniform sampler2D u_StripesTexture; +#endif +#ifdef APPLY_CEL_LIGHT +uniform samplerCube u_CelLightTexture; +#endif + +void main(void) +{ + myhalf4 inColor = myhalf4(qf_FrontColor); + + myhalf4 tempColor; + + myhalf4 outColor; + outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); + +#ifdef APPLY_ENTITY_DECAL +#ifdef APPLY_ENTITY_DECAL_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_ENTITY_DECAL + +#ifdef APPLY_DIFFUSE + outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord)); +#endif + + outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube)); + +#ifdef APPLY_STRIPES +#ifdef APPLY_STRIPES_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_STRIPES_ADD + +#ifdef APPLY_CEL_LIGHT +#ifdef APPLY_CEL_LIGHT_ADD + outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); +#else + tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_CEL_LIGHT + +#ifdef APPLY_DECAL +#ifdef APPLY_DECAL_ADD + outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_DECAL + + outColor = myhalf4(inColor * outColor); + +#ifdef APPLY_GREYSCALE + outColor.rgb = Greyscale(outColor.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(outColor); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/244.shader_test b/shaders/warsow/244.shader_test new file mode 100644 index 0000000..8688157 --- /dev/null +++ b/shaders/warsow/244.shader_test @@ -0,0 +1,1421 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 3 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +qf_varying vec3 v_TexCoordCube; + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +uniform mat4 u_ReflectionTexMatrix; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#ifdef APPLY_FOG_COLOR + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); + + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform sampler2D u_BaseTexture; +uniform samplerCube u_CelShadeTexture; + +#ifdef APPLY_DIFFUSE +uniform sampler2D u_DiffuseTexture; +#endif +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif +#ifdef APPLY_STRIPES +uniform sampler2D u_StripesTexture; +#endif +#ifdef APPLY_CEL_LIGHT +uniform samplerCube u_CelLightTexture; +#endif + +void main(void) +{ + myhalf4 inColor = myhalf4(qf_FrontColor); + + myhalf4 tempColor; + + myhalf4 outColor; + outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); + +#ifdef APPLY_ENTITY_DECAL +#ifdef APPLY_ENTITY_DECAL_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_ENTITY_DECAL + +#ifdef APPLY_DIFFUSE + outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord)); +#endif + + outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube)); + +#ifdef APPLY_STRIPES +#ifdef APPLY_STRIPES_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_STRIPES_ADD + +#ifdef APPLY_CEL_LIGHT +#ifdef APPLY_CEL_LIGHT_ADD + outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); +#else + tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_CEL_LIGHT + +#ifdef APPLY_DECAL +#ifdef APPLY_DECAL_ADD + outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_DECAL + + outColor = myhalf4(inColor * outColor); + +#ifdef APPLY_GREYSCALE + outColor.rgb = Greyscale(outColor.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(outColor); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 3 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +qf_varying vec3 v_TexCoordCube; + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +uniform mat4 u_ReflectionTexMatrix; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#ifdef APPLY_FOG_COLOR + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + v_TexCoordCube = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); + + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform sampler2D u_BaseTexture; +uniform samplerCube u_CelShadeTexture; + +#ifdef APPLY_DIFFUSE +uniform sampler2D u_DiffuseTexture; +#endif +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif +#ifdef APPLY_STRIPES +uniform sampler2D u_StripesTexture; +#endif +#ifdef APPLY_CEL_LIGHT +uniform samplerCube u_CelLightTexture; +#endif + +void main(void) +{ + myhalf4 inColor = myhalf4(qf_FrontColor); + + myhalf4 tempColor; + + myhalf4 outColor; + outColor = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); + +#ifdef APPLY_ENTITY_DECAL +#ifdef APPLY_ENTITY_DECAL_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_ENTITY_DECAL + +#ifdef APPLY_DIFFUSE + outColor.rgb *= myhalf3(qf_texture(u_DiffuseTexture, v_TexCoord)); +#endif + + outColor.rgb *= myhalf3(qf_textureCube(u_CelShadeTexture, v_TexCoordCube)); + +#ifdef APPLY_STRIPES +#ifdef APPLY_STRIPES_ADD + outColor.rgb += myhalf3(u_EntityColor.rgb) * myhalf3(qf_texture(u_StripesTexture, v_TexCoord)); +#else + tempColor = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_StripesTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_STRIPES_ADD + +#ifdef APPLY_CEL_LIGHT +#ifdef APPLY_CEL_LIGHT_ADD + outColor.rgb += myhalf3(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); +#else + tempColor = myhalf4(qf_textureCube(u_CelLightTexture, v_TexCoordCube)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_CEL_LIGHT + +#ifdef APPLY_DECAL +#ifdef APPLY_DECAL_ADD + outColor.rgb += myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); +#else + tempColor = myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + outColor.rgb = mix(outColor.rgb, tempColor.rgb, tempColor.a); +#endif +#endif // APPLY_DECAL + + outColor = myhalf4(inColor * outColor); + +#ifdef APPLY_GREYSCALE + outColor.rgb = Greyscale(outColor.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + outColor.rgb = mix(outColor.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(outColor); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/247.shader_test b/shaders/warsow/247.shader_test new file mode 100644 index 0000000..33c4793 --- /dev/null +++ b/shaders/warsow/247.shader_test @@ -0,0 +1,1675 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 3 +#define APPLY_PCF + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) +#endif + + +#ifndef NUM_SHADOWS +#define NUM_SHADOWS 1 +#endif + +qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS]; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS]; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + + for (int i = 0; i < NUM_SHADOWS; i++) + { + v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position; + // a trick whish allows us not to perform the + // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)' + // computation in the fragment shader + v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5; + } +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_RGB_SHADOW +uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy))) +#else +uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) float(qf_shadow(t,v)) +#endif + +uniform float u_ShadowAlpha; +uniform float u_ShadowProjDistance[NUM_SHADOWS]; +uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS]; + +void main(void) +{ + float finalcolor = 1.0; + +#if NUM_SHADOWS >= 1 +#define SHADOW_INDEX 0 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 2 +#define SHADOW_INDEX 1 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 3 +#define SHADOW_INDEX 2 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 4 +#define SHADOW_INDEX 3 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + + qf_FragColor = vec4(vec3(finalcolor),1.0); +} + +#endif // FRAGMENT_SHADER + + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 3 +#define APPLY_PCF + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) +#endif + + +#ifndef NUM_SHADOWS +#define NUM_SHADOWS 1 +#endif + +qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS]; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS]; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + + for (int i = 0; i < NUM_SHADOWS; i++) + { + v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position; + // a trick whish allows us not to perform the + // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)' + // computation in the fragment shader + v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5; + } +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_RGB_SHADOW +uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy))) +#else +uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) float(qf_shadow(t,v)) +#endif + +uniform float u_ShadowAlpha; +uniform float u_ShadowProjDistance[NUM_SHADOWS]; +uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS]; + +void main(void) +{ + float finalcolor = 1.0; + +#if NUM_SHADOWS >= 1 +#define SHADOW_INDEX 0 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 2 +#define SHADOW_INDEX 1 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 3 +#define SHADOW_INDEX 2 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 4 +#define SHADOW_INDEX 3 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + + qf_FragColor = vec4(vec3(finalcolor),1.0); +} + +#endif // FRAGMENT_SHADER + + diff --git a/shaders/warsow/25.shader_test b/shaders/warsow/25.shader_test index 7b223e1..7ad57db 100644 --- a/shaders/warsow/25.shader_test +++ b/shaders/warsow/25.shader_test @@ -1,132 +1,5295 @@ [require] GLSL >= 1.10 -[fragment shader] -#define FRAGMENT_SHADER -// Warsow GLSL shader - -#if !defined(__GLSL_CG_DATA_TYPES) +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI #define M_TWOPI 6.28318530717958647692 +#endif -varying vec2 TexCoord; +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif -#ifdef VERTEX_SHADER -// Vertex shader +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; -uniform float TurbAmplitude, TurbPhase; +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif -void main(void) +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) { -gl_FrontColor = gl_Color; +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -vec4 turb; -turb = vec4(gl_MultiTexCoord0); -turb.s += TurbAmplitude * sin( ((gl_MultiTexCoord0.t / 4.0 + TurbPhase)) * M_TWOPI ); -turb.t += TurbAmplitude * sin( ((gl_MultiTexCoord0.s / 4.0 + TurbPhase)) * M_TWOPI ); -TexCoord = vec2(gl_TextureMatrix[0] * turb); +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -gl_Position = ftransform(); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} } -#endif // VERTEX_SHADER +float len = length(DQReal); +DQReal /= len; +DQDual /= len; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; -#ifdef FRAGMENT_SHADER -// Fragment shader +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} -uniform sampler2D BaseTexture; +// use defines to overload the transform function -void main(void) +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) { +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; -myhalf4 color; +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -color = myhalf4(gl_Color) * myhalf4(texture2D(BaseTexture, TexCoord)); +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -gl_FragColor = vec4(color); +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} } -#endif // FRAGMENT_SHADER +float len = length(DQReal); +DQReal /= len; +DQDual /= len; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif -[vertex shader] -#define VERTEX_SHADER -// Warsow GLSL shader +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} -#if !defined(__GLSL_CG_DATA_TYPES) -#define myhalf float -#define myhalf2 vec2 -#define myhalf3 vec3 -#define myhalf4 vec4 +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#define M_TWOPI 6.28318530717958647692 +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -varying vec2 TexCoord; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} +#endif #ifdef VERTEX_SHADER -// Vertex shader +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) -uniform float TurbAmplitude, TurbPhase; +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -void main(void) +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) { -gl_FrontColor = gl_Color; +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; -vec4 turb; -turb = vec4(gl_MultiTexCoord0); -turb.s += TurbAmplitude * sin( ((gl_MultiTexCoord0.t / 4.0 + TurbPhase)) * M_TWOPI ); -turb.t += TurbAmplitude * sin( ((gl_MultiTexCoord0.s / 4.0 + TurbPhase)) * M_TWOPI ); -TexCoord = vec2(gl_TextureMatrix[0] * turb); +uniform myhalf2 u_BlendMix; -gl_Position = ftransform(); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +qf_varying vec2 v_TexCoord; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); #endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif } -#endif // VERTEX_SHADER +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef FRAGMENT_SHADER -// Fragment shader +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} -uniform sampler2D BaseTexture; void main(void) { + gl_Position = u_ModelViewProjectionMatrix * a_Position; + v_TexCoord = a_TexCoord; +} -myhalf4 color; +#endif // VERTEX_SHADER -color = myhalf4(gl_Color) * myhalf4(texture2D(BaseTexture, TexCoord)); +#ifdef FRAGMENT_SHADER +// Fragment shader -gl_FragColor = vec4(color); -} +#define FXAA_PC 1 +#if QF_GLSL_VERSION >= 130 +# define FXAA_GLSL_130 1 +#else +# define FXAA_GLSL_120 1 +#endif +# ifdef GL_ARB_gpu_shader5 +# extension GL_ARB_gpu_shader5 : enable +# endif +#define FXAA_GREEN_AS_LUMA 1 +#define FXAA_QUALITY_X_PRESET 23 + +uniform sampler2D u_BaseTexture; + +#ifdef GL_ARB_gpu_shader5 +/*============================================================================ + + + NVIDIA FXAA 3.11 by TIMOTHY LOTTES + + +------------------------------------------------------------------------------ +COPYRIGHT (C) 2010, 2011 NVIDIA CORPORATION. ALL RIGHTS RESERVED. +------------------------------------------------------------------------------ +TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED +*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA +OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR +CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR +LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, +OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE +THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +------------------------------------------------------------------------------ + INTEGRATION CHECKLIST +------------------------------------------------------------------------------ +(1.) +In the shader source, setup defines for the desired configuration. +When providing multiple shaders (for different presets), +simply setup the defines differently in multiple files. +Example, + + #define FXAA_PC 1 + #define FXAA_HLSL_5 1 + #define FXAA_QUALITY_X_PRESET 12 + +Or, + + #define FXAA_360 1 + +Or, + + #define FXAA_PS3 1 + +Etc. + +(2.) +Then include this file, + + #include "Fxaa3_11.h" + +(3.) +Then call the FXAA pixel shader from within your desired shader. +Look at the FXAA Quality FxaaPixelShader() for docs on inputs. +As for FXAA 3.11 all inputs for all shaders are the same +to enable easy porting between platforms. + + return FxaaPixelShader(...); + +(4.) +Insure pass prior to FXAA outputs RGBL (see next section). +Or use, + + #define FXAA_GREEN_AS_LUMA 1 + +(5.) +Setup engine to provide the following constants +which are used in the FxaaPixelShader() inputs, + + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir + +Look at the FXAA Quality FxaaPixelShader() for docs on inputs. + +(6.) +Have FXAA vertex shader run as a full screen triangle, +and output "pos" and "fxaaConsolePosPos" +such that inputs in the pixel shader provide, + + // {xy} = center of pixel + FxaaFloat2 pos, + + // {xy_X_} = upper left of pixel + // {_X_zw} = lower right of pixel + FxaaFloat4 fxaaConsolePosPos, + +(7.) +Insure the texture sampler(s) used by FXAA are set to bilinear filtering. + + +------------------------------------------------------------------------------ + INTEGRATION - RGBL AND COLORSPACE +------------------------------------------------------------------------------ +FXAA3 requires RGBL as input unless the following is set, + + #define FXAA_GREEN_AS_LUMA 1 + +In which case the engine uses green in place of luma, +and requires RGB input is in a non-linear colorspace. + +RGB should be LDR (low dynamic range). +Specifically do FXAA after tonemapping. + +RGB data as returned by a texture fetch can be non-linear, +or linear when FXAA_GREEN_AS_LUMA is not set. +Note an "sRGB format" texture counts as linear, +because the result of a texture fetch is linear data. +Regular "RGBA8" textures in the sRGB colorspace are non-linear. + +If FXAA_GREEN_AS_LUMA is not set, +luma must be stored in the alpha channel prior to running FXAA. +This luma should be in a perceptual space (could be gamma 2.0). +Example pass before FXAA where output is gamma 2.0 encoded, + + color.rgb = ToneMap(color.rgb); // linear color output + color.rgb = sqrt(color.rgb); // gamma 2.0 color output + return color; + +To use FXAA, + + color.rgb = ToneMap(color.rgb); // linear color output + color.rgb = sqrt(color.rgb); // gamma 2.0 color output + color.a = dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114)); // compute luma + return color; + +Another example where output is linear encoded, +say for instance writing to an sRGB formated render target, +where the render target does the conversion back to sRGB after blending, + + color.rgb = ToneMap(color.rgb); // linear color output + return color; + +To use FXAA, + + color.rgb = ToneMap(color.rgb); // linear color output + color.a = sqrt(dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114))); // compute luma + return color; + +Getting luma correct is required for the algorithm to work correctly. + + +------------------------------------------------------------------------------ + BEING LINEARLY CORRECT? +------------------------------------------------------------------------------ +Applying FXAA to a framebuffer with linear RGB color will look worse. +This is very counter intuitive, but happends to be true in this case. +The reason is because dithering artifacts will be more visiable +in a linear colorspace. + + +------------------------------------------------------------------------------ + COMPLEX INTEGRATION +------------------------------------------------------------------------------ +Q. What if the engine is blending into RGB before wanting to run FXAA? + +A. In the last opaque pass prior to FXAA, + have the pass write out luma into alpha. + Then blend into RGB only. + FXAA should be able to run ok + assuming the blending pass did not any add aliasing. + This should be the common case for particles and common blending passes. + +A. Or use FXAA_GREEN_AS_LUMA. + +============================================================================*/ + +/*============================================================================ + + INTEGRATION KNOBS + +============================================================================*/ +// +// FXAA_PS3 and FXAA_360 choose the console algorithm (FXAA3 CONSOLE). +// FXAA_360_OPT is a prototype for the new optimized 360 version. +// +// 1 = Use API. +// 0 = Don't use API. +// +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_PS3 + #define FXAA_PS3 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_360 + #define FXAA_360 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_360_OPT + #define FXAA_360_OPT 0 +#endif +/*==========================================================================*/ +#ifndef FXAA_PC + // + // FXAA Quality + // The high quality PC algorithm. + // + #define FXAA_PC 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_PC_CONSOLE + // + // The console algorithm for PC is included + // for developers targeting really low spec machines. + // Likely better to just run FXAA_PC, and use a really low preset. + // + #define FXAA_PC_CONSOLE 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GLSL_120 + #define FXAA_GLSL_120 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GLSL_130 + #define FXAA_GLSL_130 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_3 + #define FXAA_HLSL_3 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_4 + #define FXAA_HLSL_4 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_5 + #define FXAA_HLSL_5 0 +#endif +/*==========================================================================*/ +#ifndef FXAA_GREEN_AS_LUMA + // + // For those using non-linear color, + // and either not able to get luma in alpha, or not wanting to, + // this enables FXAA to run using green as a proxy for luma. + // So with this enabled, no need to pack luma in alpha. + // + // This will turn off AA on anything which lacks some amount of green. + // Pure red and blue or combination of only R and B, will get no AA. + // + // Might want to lower the settings for both, + // fxaaConsoleEdgeThresholdMin + // fxaaQualityEdgeThresholdMin + // In order to insure AA does not get turned off on colors + // which contain a minor amount of green. + // + // 1 = On. + // 0 = Off. + // + #define FXAA_GREEN_AS_LUMA 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_EARLY_EXIT + // + // Controls algorithm's early exit path. + // On PS3 turning this ON adds 2 cycles to the shader. + // On 360 turning this OFF adds 10ths of a millisecond to the shader. + // Turning this off on console will result in a more blurry image. + // So this defaults to on. + // + // 1 = On. + // 0 = Off. + // + #define FXAA_EARLY_EXIT 1 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_DISCARD + // + // Only valid for PC OpenGL currently. + // Probably will not work when FXAA_GREEN_AS_LUMA = 1. + // + // 1 = Use discard on pixels which don't need AA. + // For APIs which enable concurrent TEX+ROP from same surface. + // 0 = Return unchanged color on pixels which don't need AA. + // + #define FXAA_DISCARD 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_FAST_PIXEL_OFFSET + // + // Used for GLSL 120 only. + // + // 1 = GL API supports fast pixel offsets + // 0 = do not use fast pixel offsets + // + #ifdef GL_EXT_gpu_shader4 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifdef GL_NV_gpu_shader5 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifdef GL_ARB_gpu_shader5 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifndef FXAA_FAST_PIXEL_OFFSET + #define FXAA_FAST_PIXEL_OFFSET 0 + #endif +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GATHER4_ALPHA + // + // 1 = API supports gather4 on alpha channel. + // 0 = API does not support gather4 on alpha channel. + // + #if (FXAA_HLSL_5 == 1) + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifdef GL_ARB_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifdef GL_NV_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifndef FXAA_GATHER4_ALPHA + #define FXAA_GATHER4_ALPHA 0 + #endif +#endif + +/*============================================================================ + FXAA CONSOLE PS3 - TUNING KNOBS +============================================================================*/ +#ifndef FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS + // + // Consoles the sharpness of edges on PS3 only. + // Non-PS3 tuning is done with shader input. + // + // Due to the PS3 being ALU bound, + // there are only two safe values here: 4 and 8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // + // 8.0 is sharper + // 4.0 is softer + // 2.0 is really soft (good for vector graphics inputs) + // + #if 1 + #define FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS 8.0 + #endif + #if 0 + #define FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS 4.0 + #endif + #if 0 + #define FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS 2.0 + #endif +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_CONSOLE_X_PS3_EDGE_THRESHOLD + // + // Only effects PS3. + // Non-PS3 tuning is done with shader input. + // + // The minimum amount of local contrast required to apply algorithm. + // The console setting has a different mapping than the quality setting. + // + // This only applies when FXAA_EARLY_EXIT is 1. + // + // Due to the PS3 being ALU bound, + // there are only two safe values here: 0.25 and 0.125. + // These options use the shaders ability to a free *|/ by 2|4|8. + // + // 0.125 leaves less aliasing, but is softer + // 0.25 leaves more aliasing, and is sharper + // + #if 1 + #define FXAA_CONSOLE_X_PS3_EDGE_THRESHOLD 0.125 + #else + #define FXAA_CONSOLE_X_PS3_EDGE_THRESHOLD 0.25 + #endif +#endif + +/*============================================================================ + FXAA QUALITY - TUNING KNOBS +------------------------------------------------------------------------------ +NOTE the other tuning knobs are now in the shader function inputs! +============================================================================*/ +#ifndef FXAA_QUALITY_X_PRESET + // + // Choose the quality preset. + // This needs to be compiled into the shader as it effects code. + // Best option to include multiple presets is to + // in each shader define the preset, then include this file. + // + // OPTIONS + // ----------------------------------------------------------------------- + // 10 to 15 - default medium dither (10=fastest, 15=highest quality) + // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality) + // 39 - no dither, very expensive + // + // NOTES + // ----------------------------------------------------------------------- + // 12 = slightly faster then FXAA 3.9 and higher edge quality (default) + // 13 = about same speed as FXAA 3.9 and better than 12 + // 23 = closest to FXAA 3.9 visually and performance wise + // _ = the lowest digit is directly related to performance + // _ = the highest digit is directly related to style + // + #define FXAA_QUALITY_X_PRESET 12 +#endif + + +/*============================================================================ + + FXAA QUALITY - PRESETS + +============================================================================*/ + +/*============================================================================ + FXAA QUALITY - MEDIUM DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY_X_PRESET == 10) + #define FXAA_QUALITY_X_PS 3 + #define FXAA_QUALITY_X_P0 1.5 + #define FXAA_QUALITY_X_P1 3.0 + #define FXAA_QUALITY_X_P2 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 11) + #define FXAA_QUALITY_X_PS 4 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 3.0 + #define FXAA_QUALITY_X_P3 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 12) + #define FXAA_QUALITY_X_PS 5 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 4.0 + #define FXAA_QUALITY_X_P4 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 13) + #define FXAA_QUALITY_X_PS 6 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 2.0 + #define FXAA_QUALITY_X_P4 4.0 + #define FXAA_QUALITY_X_P5 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 14) + #define FXAA_QUALITY_X_PS 7 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 2.0 + #define FXAA_QUALITY_X_P4 2.0 + #define FXAA_QUALITY_X_P5 4.0 + #define FXAA_QUALITY_X_P6 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 15) + #define FXAA_QUALITY_X_PS 8 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 2.0 + #define FXAA_QUALITY_X_P4 2.0 + #define FXAA_QUALITY_X_P5 2.0 + #define FXAA_QUALITY_X_P6 4.0 + #define FXAA_QUALITY_X_P7 12.0 +#endif + +/*============================================================================ + FXAA QUALITY - LOW DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY_X_PRESET == 20) + #define FXAA_QUALITY_X_PS 3 + #define FXAA_QUALITY_X_P0 1.5 + #define FXAA_QUALITY_X_P1 2.0 + #define FXAA_QUALITY_X_P2 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 21) + #define FXAA_QUALITY_X_PS 4 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 22) + #define FXAA_QUALITY_X_PS 5 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 2.0 + #define FXAA_QUALITY_X_P4 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 23) + #define FXAA_QUALITY_X_PS 6 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 2.0 + #define FXAA_QUALITY_X_P4 2.0 + #define FXAA_QUALITY_X_P5 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 24) + #define FXAA_QUALITY_X_PS 7 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 2.0 + #define FXAA_QUALITY_X_P4 2.0 + #define FXAA_QUALITY_X_P5 3.0 + #define FXAA_QUALITY_X_P6 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 25) + #define FXAA_QUALITY_X_PS 8 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 2.0 + #define FXAA_QUALITY_X_P4 2.0 + #define FXAA_QUALITY_X_P5 2.0 + #define FXAA_QUALITY_X_P6 4.0 + #define FXAA_QUALITY_X_P7 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 26) + #define FXAA_QUALITY_X_PS 9 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 2.0 + #define FXAA_QUALITY_X_P4 2.0 + #define FXAA_QUALITY_X_P5 2.0 + #define FXAA_QUALITY_X_P6 2.0 + #define FXAA_QUALITY_X_P7 4.0 + #define FXAA_QUALITY_X_P8 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 27) + #define FXAA_QUALITY_X_PS 10 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 2.0 + #define FXAA_QUALITY_X_P4 2.0 + #define FXAA_QUALITY_X_P5 2.0 + #define FXAA_QUALITY_X_P6 2.0 + #define FXAA_QUALITY_X_P7 2.0 + #define FXAA_QUALITY_X_P8 4.0 + #define FXAA_QUALITY_X_P9 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 28) + #define FXAA_QUALITY_X_PS 11 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 2.0 + #define FXAA_QUALITY_X_P4 2.0 + #define FXAA_QUALITY_X_P5 2.0 + #define FXAA_QUALITY_X_P6 2.0 + #define FXAA_QUALITY_X_P7 2.0 + #define FXAA_QUALITY_X_P8 2.0 + #define FXAA_QUALITY_X_P9 4.0 + #define FXAA_QUALITY_X_P10 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 29) + #define FXAA_QUALITY_X_PS 12 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 2.0 + #define FXAA_QUALITY_X_P4 2.0 + #define FXAA_QUALITY_X_P5 2.0 + #define FXAA_QUALITY_X_P6 2.0 + #define FXAA_QUALITY_X_P7 2.0 + #define FXAA_QUALITY_X_P8 2.0 + #define FXAA_QUALITY_X_P9 2.0 + #define FXAA_QUALITY_X_P10 4.0 + #define FXAA_QUALITY_X_P11 8.0 +#endif + +/*============================================================================ + FXAA QUALITY - EXTREME QUALITY +============================================================================*/ +#if (FXAA_QUALITY_X_PRESET == 39) + #define FXAA_QUALITY_X_PS 12 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.0 + #define FXAA_QUALITY_X_P2 1.0 + #define FXAA_QUALITY_X_P3 1.0 + #define FXAA_QUALITY_X_P4 1.0 + #define FXAA_QUALITY_X_P5 1.5 + #define FXAA_QUALITY_X_P6 2.0 + #define FXAA_QUALITY_X_P7 2.0 + #define FXAA_QUALITY_X_P8 2.0 + #define FXAA_QUALITY_X_P9 2.0 + #define FXAA_QUALITY_X_P10 4.0 + #define FXAA_QUALITY_X_P11 8.0 +#endif + + + +/*============================================================================ + + API PORTING + +============================================================================*/ +#if (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1) + #define FxaaBool bool + #define FxaaDiscard discard + #define FxaaFloat float + #define FxaaFloat2 vec2 + #define FxaaFloat3 vec3 + #define FxaaFloat4 vec4 + #define FxaaHalf float + #define FxaaHalf2 vec2 + #define FxaaHalf3 vec3 + #define FxaaHalf4 vec4 + #define FxaaInt2 ivec2 + #define FxaaSat(x) clamp(x, 0.0, 1.0) + #define FxaaTex sampler2D +#else + #define FxaaBool bool + #define FxaaDiscard clip(-1) + #define FxaaFloat float + #define FxaaFloat2 float2 + #define FxaaFloat3 float3 + #define FxaaFloat4 float4 + #define FxaaHalf half + #define FxaaHalf2 half2 + #define FxaaHalf3 half3 + #define FxaaHalf4 half4 + #define FxaaSat(x) saturate(x) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_GLSL_120 == 1) + // Requires, + // #version 120 + // And at least, + // #extension GL_EXT_gpu_shader4 : enable + // (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9) + #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0) + #if (FXAA_FAST_PIXEL_OFFSET == 1) + #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o) + #else + #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0) + #endif + #if (FXAA_GATHER4_ALPHA == 1) + // use #extension GL_ARB_gpu_shader5 : enable + #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) + #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) + #define FxaaTexGreen4(t, p) textureGather(t, p, 1) + #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) + #endif +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_GLSL_130 == 1) + // Requires "#version 130" or better + #define FxaaTexTop(t, p) textureLod(t, p, 0.0) + #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o) + #if (FXAA_GATHER4_ALPHA == 1) + // use #extension GL_ARB_gpu_shader5 : enable + #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) + #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) + #define FxaaTexGreen4(t, p) textureGather(t, p, 1) + #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) + #endif +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1) || (FXAA_PS3 == 1) + #define FxaaInt2 float2 + #define FxaaTex sampler2D + #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0)) + #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0)) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_4 == 1) + #define FxaaInt2 int2 + struct FxaaTex { SamplerState smpl; Texture2D tex; }; + #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) + #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_5 == 1) + #define FxaaInt2 int2 + struct FxaaTex { SamplerState smpl; Texture2D tex; }; + #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) + #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) + #define FxaaTexAlpha4(t, p) t.tex.GatherAlpha(t.smpl, p) + #define FxaaTexOffAlpha4(t, p, o) t.tex.GatherAlpha(t.smpl, p, o) + #define FxaaTexGreen4(t, p) t.tex.GatherGreen(t.smpl, p) + #define FxaaTexOffGreen4(t, p, o) t.tex.GatherGreen(t.smpl, p, o) +#endif -#endif // FRAGMENT_SHADER +/*============================================================================ + GREEN AS LUMA OPTION SUPPORT FUNCTION +============================================================================*/ +#if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; } +#else + FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; } +#endif + + + + +/*============================================================================ + + FXAA3 QUALITY - PC + +============================================================================*/ +#if (FXAA_PC == 1) +/*--------------------------------------------------------------------------*/ +FxaaFloat4 FxaaPixelShader( + // + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy} = center of pixel + FxaaFloat2 pos, + // + // Used only for FXAA Console, and not used on the 360 version. + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy_X_} = upper left of pixel + // {_X_zw} = lower right of pixel + FxaaFloat4 fxaaConsolePosPos, + // + // Input color texture. + // {rgb_} = color in linear or perceptual color space + // if (FXAA_GREEN_AS_LUMA == 0) + // {_X__a} = luma in perceptual color space (not linear) + FxaaTex tex, + // + // Only used on the optimized 360 version of FXAA Console. + // For everything but 360, just use the same input here as for "tex". + // For 360, same texture, just alias with a 2nd sampler. + // This sampler needs to have an exponent bias of -1. + FxaaTex fxaaConsole360TexExpBiasNegOne, + // + // Only used on the optimized 360 version of FXAA Console. + // For everything but 360, just use the same input here as for "tex". + // For 360, same texture, just alias with a 3nd sampler. + // This sampler needs to have an exponent bias of -2. + FxaaTex fxaaConsole360TexExpBiasNegTwo, + // + // Only used on FXAA Quality. + // This must be from a constant/uniform. + // {x_} = 1.0/screenWidthInPixels + // {_y} = 1.0/screenHeightInPixels + FxaaFloat2 fxaaQualityRcpFrame, + // + // Only used on FXAA Console. + // This must be from a constant/uniform. + // This effects sub-pixel AA quality and inversely sharpness. + // Where N ranges between, + // N = 0.50 (default) + // N = 0.33 (sharper) + // {x_X__} = -N/screenWidthInPixels + // {_y_X_} = -N/screenHeightInPixels + // {_X_z_} = N/screenWidthInPixels + // {_X__w} = N/screenHeightInPixels + FxaaFloat4 fxaaConsoleRcpFrameOpt, + // + // Only used on FXAA Console. + // Not used on 360, but used on PS3 and PC. + // This must be from a constant/uniform. + // {x_X__} = -2.0/screenWidthInPixels + // {_y_X_} = -2.0/screenHeightInPixels + // {_X_z_} = 2.0/screenWidthInPixels + // {_X__w} = 2.0/screenHeightInPixels + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + // + // Only used on FXAA Console. + // Only used on 360 in place of fxaaConsoleRcpFrameOpt2. + // This must be from a constant/uniform. + // {x_X__} = 8.0/screenWidthInPixels + // {_y_X_} = 8.0/screenHeightInPixels + // {_X_z_} = -4.0/screenWidthInPixels + // {_X__w} = -4.0/screenHeightInPixels + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY_X_SUBPIX define. + // It is here now to allow easier tuning. + // Choose the amount of sub-pixel aliasing removal. + // This can effect sharpness. + // 1.00 - upper limit (softer) + // 0.75 - default amount of filtering + // 0.50 - lower limit (sharper, less sub-pixel aliasing removal) + // 0.25 - almost off + // 0.00 - completely off + FxaaFloat fxaaQualitySubpix, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY_X_EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // The minimum amount of local contrast required to apply algorithm. + // 0.333 - too little (faster) + // 0.250 - low quality + // 0.166 - default + // 0.125 - high quality + // 0.063 - overkill (slower) + FxaaFloat fxaaQualityEdgeThreshold, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY_X_EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // 0.0833 - upper limit (default, the start of visible unfiltered edges) + // 0.0625 - high quality (faster) + // 0.0312 - visible limit (slower) + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + FxaaFloat fxaaQualityEdgeThresholdMin, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE_X_EDGE_SHARPNESS define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS for PS3. + // Due to the PS3 being ALU bound, + // there are only three safe values here: 2 and 4 and 8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // For all other platforms can be a non-power of two. + // 8.0 is sharper (default!!!) + // 4.0 is softer + // 2.0 is really soft (good only for vector graphics inputs) + FxaaFloat fxaaConsoleEdgeSharpness, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE_X_EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE_X_PS3_EDGE_THRESHOLD for PS3. + // Due to the PS3 being ALU bound, + // there are only two safe values here: 1/4 and 1/8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // The console setting has a different mapping than the quality setting. + // Other platforms can use other values. + // 0.125 leaves less aliasing, but is softer (default!!!) + // 0.25 leaves more aliasing, and is sharper + FxaaFloat fxaaConsoleEdgeThreshold, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE_X_EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // The console setting has a different mapping than the quality setting. + // This only applies when FXAA_EARLY_EXIT is 1. + // This does not apply to PS3, + // PS3 was simplified to avoid more shader instructions. + // 0.06 - faster but more aliasing in darks + // 0.05 - default + // 0.04 - slower and less aliasing in darks + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + FxaaFloat fxaaConsoleEdgeThresholdMin, + // + // Extra constants for 360 FXAA Console only. + // Use zeros or anything else for other platforms. + // These must be in physical constant registers and NOT immedates. + // Immedates will result in compiler un-optimizing. + // {xyzw} = float4(1.0, -1.0, 0.25, -0.25) + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posM; + posM.x = pos.x; + posM.y = pos.y; + #if (FXAA_GATHER4_ALPHA == 1) + #if (FXAA_DISCARD == 0) + FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); + #if (FXAA_GREEN_AS_LUMA == 0) + #define lumaM rgbyM.w + #else + #define lumaM rgbyM.y + #endif + #endif + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM); + FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1)); + #else + FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM); + FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1)); + #endif + #if (FXAA_DISCARD == 1) + #define lumaM luma4A.w + #endif + #define lumaE luma4A.z + #define lumaS luma4A.x + #define lumaSE luma4A.y + #define lumaNW luma4B.w + #define lumaN luma4B.z + #define lumaW luma4B.x + #else + FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); + #if (FXAA_GREEN_AS_LUMA == 0) + #define lumaM rgbyM.w + #else + #define lumaM rgbyM.y + #endif + FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy)); + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat maxSM = max(lumaS, lumaM); + FxaaFloat minSM = min(lumaS, lumaM); + FxaaFloat maxESM = max(lumaE, maxSM); + FxaaFloat minESM = min(lumaE, minSM); + FxaaFloat maxWN = max(lumaN, lumaW); + FxaaFloat minWN = min(lumaN, lumaW); + FxaaFloat rangeMax = max(maxWN, maxESM); + FxaaFloat rangeMin = min(minWN, minESM); + FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold; + FxaaFloat range = rangeMax - rangeMin; + FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled); + FxaaBool earlyExit = range < rangeMaxClamped; +/*--------------------------------------------------------------------------*/ + if(earlyExit) + #if (FXAA_DISCARD == 1) + FxaaDiscard; + #else + return rgbyM; + #endif +/*--------------------------------------------------------------------------*/ + #if (FXAA_GATHER4_ALPHA == 0) + FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); + #else + FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNS = lumaN + lumaS; + FxaaFloat lumaWE = lumaW + lumaE; + FxaaFloat subpixRcpRange = 1.0/range; + FxaaFloat subpixNSWE = lumaNS + lumaWE; + FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS; + FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNESE = lumaNE + lumaSE; + FxaaFloat lumaNWNE = lumaNW + lumaNE; + FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE; + FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNWSW = lumaNW + lumaSW; + FxaaFloat lumaSWSE = lumaSW + lumaSE; + FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); + FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); + FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; + FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE; + FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4; + FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4; +/*--------------------------------------------------------------------------*/ + FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE; + FxaaFloat lengthSign = fxaaQualityRcpFrame.x; + FxaaBool horzSpan = edgeHorz >= edgeVert; + FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; +/*--------------------------------------------------------------------------*/ + if(!horzSpan) lumaN = lumaW; + if(!horzSpan) lumaS = lumaE; + if(horzSpan) lengthSign = fxaaQualityRcpFrame.y; + FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM; +/*--------------------------------------------------------------------------*/ + FxaaFloat gradientN = lumaN - lumaM; + FxaaFloat gradientS = lumaS - lumaM; + FxaaFloat lumaNN = lumaN + lumaM; + FxaaFloat lumaSS = lumaS + lumaM; + FxaaBool pairN = abs(gradientN) >= abs(gradientS); + FxaaFloat gradient = max(abs(gradientN), abs(gradientS)); + if(pairN) lengthSign = -lengthSign; + FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posB; + posB.x = posM.x; + posB.y = posM.y; + FxaaFloat2 offNP; + offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x; + offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y; + if(!horzSpan) posB.x += lengthSign * 0.5; + if( horzSpan) posB.y += lengthSign * 0.5; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posN; + posN.x = posB.x - offNP.x * FXAA_QUALITY_X_P0; + posN.y = posB.y - offNP.y * FXAA_QUALITY_X_P0; + FxaaFloat2 posP; + posP.x = posB.x + offNP.x * FXAA_QUALITY_X_P0; + posP.y = posB.y + offNP.y * FXAA_QUALITY_X_P0; + FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0; + FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN)); + FxaaFloat subpixE = subpixC * subpixC; + FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP)); +/*--------------------------------------------------------------------------*/ + if(!pairN) lumaNN = lumaSS; + FxaaFloat gradientScaled = gradient * 1.0/4.0; + FxaaFloat lumaMM = lumaM - lumaNN * 0.5; + FxaaFloat subpixF = subpixD * subpixE; + FxaaBool lumaMLTZero = lumaMM < 0.0; +/*--------------------------------------------------------------------------*/ + lumaEndN -= lumaNN * 0.5; + lumaEndP -= lumaNN * 0.5; + FxaaBool doneN = abs(lumaEndN) >= gradientScaled; + FxaaBool doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P1; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P1; + FxaaBool doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P1; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P1; +/*--------------------------------------------------------------------------*/ + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P2; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P2; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P2; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P2; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_X_PS > 3) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P3; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P3; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P3; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P3; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_X_PS > 4) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P4; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P4; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P4; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P4; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_X_PS > 5) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P5; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P5; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P5; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P5; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_X_PS > 6) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P6; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P6; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P6; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P6; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_X_PS > 7) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P7; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P7; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P7; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P7; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_X_PS > 8) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P8; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P8; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P8; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P8; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_X_PS > 9) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P9; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P9; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P9; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P9; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_X_PS > 10) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P10; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P10; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P10; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P10; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_X_PS > 11) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P11; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P11; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P11; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P11; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_X_PS > 12) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P12; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P12; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P12; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P12; +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } +/*--------------------------------------------------------------------------*/ + FxaaFloat dstN = posM.x - posN.x; + FxaaFloat dstP = posP.x - posM.x; + if(!horzSpan) dstN = posM.y - posN.y; + if(!horzSpan) dstP = posP.y - posM.y; +/*--------------------------------------------------------------------------*/ + FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; + FxaaFloat spanLength = (dstP + dstN); + FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; + FxaaFloat spanLengthRcp = 1.0/spanLength; +/*--------------------------------------------------------------------------*/ + FxaaBool directionN = dstN < dstP; + FxaaFloat dst = min(dstN, dstP); + FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP; + FxaaFloat subpixG = subpixF * subpixF; + FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5; + FxaaFloat subpixH = subpixG * fxaaQualitySubpix; +/*--------------------------------------------------------------------------*/ + FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0; + FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH); + if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; + if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign; + #if (FXAA_DISCARD == 1) + return FxaaTexTop(tex, posM); + #else + return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM); + #endif +} +/*==========================================================================*/ +#endif + + + + +/*============================================================================ + + FXAA3 CONSOLE - PC VERSION + +------------------------------------------------------------------------------ +Instead of using this on PC, I'd suggest just using FXAA Quality with + #define FXAA_QUALITY_X_PRESET 10 +Or + #define FXAA_QUALITY_X_PRESET 20 +Either are higher qualilty and almost as fast as this on modern PC GPUs. +============================================================================*/ +#if (FXAA_PC_CONSOLE == 1) +/*--------------------------------------------------------------------------*/ +FxaaFloat4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xy)); + FxaaFloat lumaSw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xw)); + FxaaFloat lumaNe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zy)); + FxaaFloat lumaSe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zw)); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyM = FxaaTexTop(tex, pos.xy); + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat lumaM = rgbyM.w; + #else + FxaaFloat lumaM = rgbyM.y; + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxNwSw = max(lumaNw, lumaSw); + lumaNe += 1.0/384.0; + FxaaFloat lumaMinNwSw = min(lumaNw, lumaSw); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxNeSe = max(lumaNe, lumaSe); + FxaaFloat lumaMinNeSe = min(lumaNe, lumaSe); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMax = max(lumaMaxNeSe, lumaMaxNwSw); + FxaaFloat lumaMin = min(lumaMinNeSe, lumaMinNwSw); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxScaled = lumaMax * fxaaConsoleEdgeThreshold; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMinM = min(lumaMin, lumaM); + FxaaFloat lumaMaxScaledClamped = max(fxaaConsoleEdgeThresholdMin, lumaMaxScaled); + FxaaFloat lumaMaxM = max(lumaMax, lumaM); + FxaaFloat dirSwMinusNe = lumaSw - lumaNe; + FxaaFloat lumaMaxSubMinM = lumaMaxM - lumaMinM; + FxaaFloat dirSeMinusNw = lumaSe - lumaNw; + if(lumaMaxSubMinM < lumaMaxScaledClamped) return rgbyM; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 dir; + dir.x = dirSwMinusNe + dirSeMinusNw; + dir.y = dirSwMinusNe - dirSeMinusNw; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 dir1 = normalize(dir.xy); + FxaaFloat4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * fxaaConsoleRcpFrameOpt.zw); + FxaaFloat4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * fxaaConsoleRcpFrameOpt.zw); +/*--------------------------------------------------------------------------*/ + FxaaFloat dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * fxaaConsoleEdgeSharpness; + FxaaFloat2 dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2 * fxaaConsoleRcpFrameOpt2.zw); + FxaaFloat4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2 * fxaaConsoleRcpFrameOpt2.zw); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyA = rgbyN1 + rgbyP1; + FxaaFloat4 rgbyB = ((rgbyN2 + rgbyP2) * 0.25) + (rgbyA * 0.25); +/*--------------------------------------------------------------------------*/ + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaBool twoTap = (rgbyB.w < lumaMin) || (rgbyB.w > lumaMax); + #else + FxaaBool twoTap = (rgbyB.y < lumaMin) || (rgbyB.y > lumaMax); + #endif + if(twoTap) rgbyB.xyz = rgbyA.xyz * 0.5; + return rgbyB; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - 360 PIXEL SHADER + +------------------------------------------------------------------------------ +This optimized version thanks to suggestions from Andy Luedke. +Should be fully tex bound in all cases. +As of the FXAA 3.11 release, I have still not tested this code, +however I fixed a bug which was in both FXAA 3.9 and FXAA 3.10. +And note this is replacing the old unoptimized version. +If it does not work, please let me know so I can fix it. +============================================================================*/ +#if (FXAA_360 == 1) +/*--------------------------------------------------------------------------*/ + [reduceTempRegUsage(4)] +float4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + float4 lumaNwNeSwSe; + #if (FXAA_GREEN_AS_LUMA == 0) + asm { + tfetch2D lumaNwNeSwSe.w_X__, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._w_X_, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._X_w_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._X__w, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false + }; + #else + asm { + tfetch2D lumaNwNeSwSe.y_X__, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._y_X_, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._X_y_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._X__y, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false + }; + #endif +/*--------------------------------------------------------------------------*/ + lumaNwNeSwSe.y += 1.0/384.0; + float2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); + float2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); + float lumaMin = min(lumaMinTemp.x, lumaMinTemp.y); + float lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y); +/*--------------------------------------------------------------------------*/ + float4 rgbyM = tex2Dlod(tex, float4(pos.xy, 0.0, 0.0)); + #if (FXAA_GREEN_AS_LUMA == 0) + float lumaMinM = min(lumaMin, rgbyM.w); + float lumaMaxM = max(lumaMax, rgbyM.w); + #else + float lumaMinM = min(lumaMin, rgbyM.y); + float lumaMaxM = max(lumaMax, rgbyM.y); + #endif + if((lumaMaxM - lumaMinM) < max(fxaaConsoleEdgeThresholdMin, lumaMax * fxaaConsoleEdgeThreshold)) return rgbyM; +/*--------------------------------------------------------------------------*/ + float2 dir; + dir.x = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.yyxx); + dir.y = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.xyxy); + dir = normalize(dir); +/*--------------------------------------------------------------------------*/ + float4 dir1 = dir.xyxy * fxaaConsoleRcpFrameOpt.xyzw; +/*--------------------------------------------------------------------------*/ + float4 dir2; + float dirAbsMinTimesC = min(abs(dir.x), abs(dir.y)) * fxaaConsoleEdgeSharpness; + dir2 = saturate(fxaaConsole360ConstDir.zzww * dir.xyxy / dirAbsMinTimesC + 0.5); + dir2 = dir2 * fxaaConsole360RcpFrameOpt2.xyxy + fxaaConsole360RcpFrameOpt2.zwzw; +/*--------------------------------------------------------------------------*/ + float4 rgbyN1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.xy, 0.0, 0.0)); + float4 rgbyP1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.zw, 0.0, 0.0)); + float4 rgbyN2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.xy, 0.0, 0.0)); + float4 rgbyP2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.zw, 0.0, 0.0)); +/*--------------------------------------------------------------------------*/ + float4 rgbyA = rgbyN1 + rgbyP1; + float4 rgbyB = rgbyN2 + rgbyP2 + rgbyA * 0.5; +/*--------------------------------------------------------------------------*/ + float4 rgbyR = ((FxaaLuma(rgbyB) - lumaMax) > 0.0) ? rgbyA : rgbyB; + rgbyR = ((FxaaLuma(rgbyB) - lumaMin) > 0.0) ? rgbyR : rgbyA; + return rgbyR; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (NO EARLY EXIT) + +============================================================================== +The code below does not exactly match the assembly. +I have a feeling that 12 cycles is possible, but was not able to get there. +Might have to increase register count to get full performance. +Note this shader does not use perspective interpolation. + +Use the following cgc options, + + --fenable-bx2 --fastmath --fastprecision --nofloatbindings + +------------------------------------------------------------------------------ + NVSHADERPERF OUTPUT +------------------------------------------------------------------------------ +For reference and to aid in debug, output of NVShaderPerf should match this, + +Shader to schedule: + 0: texpkb h0.w(TRUE), v5.zyxx, #0 + 2: addh h2.z(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x + 4: texpkb h0.w(TRUE), v5.xwxx, #0 + 6: addh h0.z(TRUE), -h2, h0.w + 7: texpkb h1.w(TRUE), v5, #0 + 9: addh h0.x(TRUE), h0.z, -h1.w + 10: addh h3.w(TRUE), h0.z, h1 + 11: texpkb h2.w(TRUE), v5.zwzz, #0 + 13: addh h0.z(TRUE), h3.w, -h2.w + 14: addh h0.x(TRUE), h2.w, h0 + 15: nrmh h1.xz(TRUE), h0_n + 16: minh_m8 h0.x(TRUE), |h1|, |h1.z| + 17: maxh h4.w(TRUE), h0, h1 + 18: divx h2.xy(TRUE), h1_n.xzzw, h0_n + 19: movr r1.zw(TRUE), v4.xxxy + 20: madr r2.xz(TRUE), -h1, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zzww, r1.zzww + 22: minh h5.w(TRUE), h0, h1 + 23: texpkb h0(TRUE), r2.xzxx, #0 + 25: madr r0.zw(TRUE), h1.xzxz, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w), r1 + 27: maxh h4.x(TRUE), h2.z, h2.w + 28: texpkb h1(TRUE), r0.zwzz, #0 + 30: addh_d2 h1(TRUE), h0, h1 + 31: madr r0.xy(TRUE), -h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 33: texpkb h0(TRUE), r0, #0 + 35: minh h4.z(TRUE), h2, h2.w + 36: fenct TRUE + 37: madr r1.xy(TRUE), h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 39: texpkb h2(TRUE), r1, #0 + 41: addh_d2 h0(TRUE), h0, h2 + 42: maxh h2.w(TRUE), h4, h4.x + 43: minh h2.x(TRUE), h5.w, h4.z + 44: addh_d2 h0(TRUE), h0, h1 + 45: slth h2.x(TRUE), h0.w, h2 + 46: sgth h2.w(TRUE), h0, h2 + 47: movh h0(TRUE), h0 + 48: addx.c0 rc(TRUE), h2, h2.w + 49: movh h0(c0.NE.x), h1 + +IPU0 ------ Simplified schedule: -------- +Pass | Unit | uOp | PC: Op +-----+--------+------+------------------------- + 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | SCB1 | add | 2: ADDh h2.z, h0.--w-, const.--x-; + | | | + 2 | SCT0/1 | mov | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; + | TEX | txl | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; + | SCB1 | add | 6: ADDh h0.z,-h2, h0.--w-; + | | | + 3 | SCT0/1 | mov | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; + | TEX | txl | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; + | SCB0 | add | 9: ADDh h0.x, h0.z---,-h1.w---; + | SCB1 | add | 10: ADDh h3.w, h0.---z, h1; + | | | + 4 | SCT0/1 | mov | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | TEX | txl | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | SCB0 | add | 14: ADDh h0.x, h2.w---, h0; + | SCB1 | add | 13: ADDh h0.z, h3.--w-,-h2.--w-; + | | | + 5 | SCT1 | mov | 15: NRMh h1.xz, h0; + | SRB | nrm | 15: NRMh h1.xz, h0; + | SCB0 | min | 16: MINh*8 h0.x, |h1|, |h1.z---|; + | SCB1 | max | 17: MAXh h4.w, h0, h1; + | | | + 6 | SCT0 | div | 18: DIVx h2.xy, h1.xz--, h0; + | SCT1 | mov | 19: MOVr r1.zw, g[TEX0].--xy; + | SCB0 | mad | 20: MADr r2.xz,-h1, const.z-w-, r1.z-w-; + | SCB1 | min | 22: MINh h5.w, h0, h1; + | | | + 7 | SCT0/1 | mov | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; + | TEX | txl | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; + | SCB0 | max | 27: MAXh h4.x, h2.z---, h2.w---; + | SCB1 | mad | 25: MADr r0.zw, h1.--xz, const, r1; + | | | + 8 | SCT0/1 | mov | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; + | TEX | txl | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; + | SCB0/1 | add | 30: ADDh/2 h1, h0, h1; + | | | + 9 | SCT0 | mad | 31: MADr r0.xy,-h2, const.xy--, r1.zw--; + | SCT1 | mov | 33: TXLr h0, r0, const.zzzz, TEX0; + | TEX | txl | 33: TXLr h0, r0, const.zzzz, TEX0; + | SCB1 | min | 35: MINh h4.z, h2, h2.--w-; + | | | + 10 | SCT0 | mad | 37: MADr r1.xy, h2, const.xy--, r1.zw--; + | SCT1 | mov | 39: TXLr h2, r1, const.zzzz, TEX0; + | TEX | txl | 39: TXLr h2, r1, const.zzzz, TEX0; + | SCB0/1 | add | 41: ADDh/2 h0, h0, h2; + | | | + 11 | SCT0 | min | 43: MINh h2.x, h5.w---, h4.z---; + | SCT1 | max | 42: MAXh h2.w, h4, h4.---x; + | SCB0/1 | add | 44: ADDh/2 h0, h0, h1; + | | | + 12 | SCT0 | set | 45: SLTh h2.x, h0.w---, h2; + | SCT1 | set | 46: SGTh h2.w, h0, h2; + | SCB0/1 | mul | 47: MOVh h0, h0; + | | | + 13 | SCT0 | mad | 48: ADDxc0_s rc, h2, h2.w---; + | SCB0/1 | mul | 49: MOVh h0(NE0.xxxx), h1; + +Pass SCT TEX SCB + 1: 0% 100% 25% + 2: 0% 100% 25% + 3: 0% 100% 50% + 4: 0% 100% 50% + 5: 0% 0% 50% + 6: 100% 0% 75% + 7: 0% 100% 75% + 8: 0% 100% 100% + 9: 0% 100% 25% + 10: 0% 100% 100% + 11: 50% 0% 100% + 12: 50% 0% 100% + 13: 25% 0% 100% + +MEAN: 17% 61% 67% + +Pass SCT0 SCT1 TEX SCB0 SCB1 + 1: 0% 0% 100% 0% 100% + 2: 0% 0% 100% 0% 100% + 3: 0% 0% 100% 100% 100% + 4: 0% 0% 100% 100% 100% + 5: 0% 0% 0% 100% 100% + 6: 100% 100% 0% 100% 100% + 7: 0% 0% 100% 100% 100% + 8: 0% 0% 100% 100% 100% + 9: 0% 0% 100% 0% 100% + 10: 0% 0% 100% 100% 100% + 11: 100% 100% 0% 100% 100% + 12: 100% 100% 0% 100% 100% + 13: 100% 0% 0% 100% 100% + +MEAN: 30% 23% 61% 76% 100% +Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 +Results 13 cycles, 3 r regs, 923,076,923 pixels/s +============================================================================*/ +#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 0) +/*--------------------------------------------------------------------------*/ +#pragma regcount 7 +#pragma disablepc all +#pragma option O3 +#pragma option OutColorPrec=fp16 +#pragma texformat default RGBA8 +/*==========================================================================*/ +half4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ +// (1) + half4 dir; + half4 lumaNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + lumaNe.w += half(1.0/512.0); + dir.x = -lumaNe.w; + dir.z = -lumaNe.w; + #else + lumaNe.y += half(1.0/512.0); + dir.x = -lumaNe.y; + dir.z = -lumaNe.y; + #endif +/*--------------------------------------------------------------------------*/ +// (2) + half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x += lumaSw.w; + dir.z += lumaSw.w; + #else + dir.x += lumaSw.y; + dir.z += lumaSw.y; + #endif +/*--------------------------------------------------------------------------*/ +// (3) + half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x -= lumaNw.w; + dir.z += lumaNw.w; + #else + dir.x -= lumaNw.y; + dir.z += lumaNw.y; + #endif +/*--------------------------------------------------------------------------*/ +// (4) + half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x += lumaSe.w; + dir.z -= lumaSe.w; + #else + dir.x += lumaSe.y; + dir.z -= lumaSe.y; + #endif +/*--------------------------------------------------------------------------*/ +// (5) + half4 dir1_pos; + dir1_pos.xy = normalize(dir.xyz).xz; + half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS); +/*--------------------------------------------------------------------------*/ +// (6) + half4 dir2_pos; + dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0)); + dir1_pos.zw = pos.xy; + dir2_pos.zw = pos.xy; + half4 temp1N; + temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; +/*--------------------------------------------------------------------------*/ +// (7) + temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); + half4 rgby1; + rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; +/*--------------------------------------------------------------------------*/ +// (8) + rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); + rgby1 = (temp1N + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (9) + half4 temp2N; + temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); +/*--------------------------------------------------------------------------*/ +// (10) + half4 rgby2; + rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); + rgby2 = (temp2N + rgby2) * 0.5; +/*--------------------------------------------------------------------------*/ +// (11) + // compilier moves these scalar ops up to other cycles + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w)); + half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w)); + #else + half lumaMin = min(min(lumaNw.y, lumaSw.y), min(lumaNe.y, lumaSe.y)); + half lumaMax = max(max(lumaNw.y, lumaSw.y), max(lumaNe.y, lumaSe.y)); + #endif + rgby2 = (rgby2 + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (12) + #if (FXAA_GREEN_AS_LUMA == 0) + bool twoTapLt = rgby2.w < lumaMin; + bool twoTapGt = rgby2.w > lumaMax; + #else + bool twoTapLt = rgby2.y < lumaMin; + bool twoTapGt = rgby2.y > lumaMax; + #endif +/*--------------------------------------------------------------------------*/ +// (13) + if(twoTapLt || twoTapGt) rgby2 = rgby1; +/*--------------------------------------------------------------------------*/ + return rgby2; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (WITH EARLY EXIT) + +============================================================================== +The code mostly matches the assembly. +I have a feeling that 14 cycles is possible, but was not able to get there. +Might have to increase register count to get full performance. +Note this shader does not use perspective interpolation. + +Use the following cgc options, + + --fenable-bx2 --fastmath --fastprecision --nofloatbindings + +Use of FXAA_GREEN_AS_LUMA currently adds a cycle (16 clks). +Will look at fixing this for FXAA 3.12. +------------------------------------------------------------------------------ + NVSHADERPERF OUTPUT +------------------------------------------------------------------------------ +For reference and to aid in debug, output of NVShaderPerf should match this, + +Shader to schedule: + 0: texpkb h0.w(TRUE), v5.zyxx, #0 + 2: addh h2.y(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x + 4: texpkb h1.w(TRUE), v5.xwxx, #0 + 6: addh h0.x(TRUE), h1.w, -h2.y + 7: texpkb h2.w(TRUE), v5.zwzz, #0 + 9: minh h4.w(TRUE), h2.y, h2 + 10: maxh h5.x(TRUE), h2.y, h2.w + 11: texpkb h0.w(TRUE), v5, #0 + 13: addh h3.w(TRUE), -h0, h0.x + 14: addh h0.x(TRUE), h0.w, h0 + 15: addh h0.z(TRUE), -h2.w, h0.x + 16: addh h0.x(TRUE), h2.w, h3.w + 17: minh h5.y(TRUE), h0.w, h1.w + 18: nrmh h2.xz(TRUE), h0_n + 19: minh_m8 h2.w(TRUE), |h2.x|, |h2.z| + 20: divx h4.xy(TRUE), h2_n.xzzw, h2_n.w + 21: movr r1.zw(TRUE), v4.xxxy + 22: maxh h2.w(TRUE), h0, h1 + 23: fenct TRUE + 24: madr r0.xy(TRUE), -h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz + 26: texpkb h0(TRUE), r0, #0 + 28: maxh h5.x(TRUE), h2.w, h5 + 29: minh h5.w(TRUE), h5.y, h4 + 30: madr r1.xy(TRUE), h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz + 32: texpkb h2(TRUE), r1, #0 + 34: addh_d2 h2(TRUE), h0, h2 + 35: texpkb h1(TRUE), v4, #0 + 37: maxh h5.y(TRUE), h5.x, h1.w + 38: minh h4.w(TRUE), h1, h5 + 39: madr r0.xy(TRUE), -h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 41: texpkb h0(TRUE), r0, #0 + 43: addh_m8 h5.z(TRUE), h5.y, -h4.w + 44: madr r2.xy(TRUE), h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 46: texpkb h3(TRUE), r2, #0 + 48: addh_d2 h0(TRUE), h0, h3 + 49: addh_d2 h3(TRUE), h0, h2 + 50: movh h0(TRUE), h3 + 51: slth h3.x(TRUE), h3.w, h5.w + 52: sgth h3.w(TRUE), h3, h5.x + 53: addx.c0 rc(TRUE), h3.x, h3 + 54: slth.c0 rc(TRUE), h5.z, h5 + 55: movh h0(c0.NE.w), h2 + 56: movh h0(c0.NE.x), h1 + +IPU0 ------ Simplified schedule: -------- +Pass | Unit | uOp | PC: Op +-----+--------+------+------------------------- + 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | SCB0 | add | 2: ADDh h2.y, h0.-w--, const.-x--; + | | | + 2 | SCT0/1 | mov | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; + | TEX | txl | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; + | SCB0 | add | 6: ADDh h0.x, h1.w---,-h2.y---; + | | | + 3 | SCT0/1 | mov | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | TEX | txl | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | SCB0 | max | 10: MAXh h5.x, h2.y---, h2.w---; + | SCB1 | min | 9: MINh h4.w, h2.---y, h2; + | | | + 4 | SCT0/1 | mov | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; + | TEX | txl | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; + | SCB0 | add | 14: ADDh h0.x, h0.w---, h0; + | SCB1 | add | 13: ADDh h3.w,-h0, h0.---x; + | | | + 5 | SCT0 | mad | 16: ADDh h0.x, h2.w---, h3.w---; + | SCT1 | mad | 15: ADDh h0.z,-h2.--w-, h0.--x-; + | SCB0 | min | 17: MINh h5.y, h0.-w--, h1.-w--; + | | | + 6 | SCT1 | mov | 18: NRMh h2.xz, h0; + | SRB | nrm | 18: NRMh h2.xz, h0; + | SCB1 | min | 19: MINh*8 h2.w, |h2.---x|, |h2.---z|; + | | | + 7 | SCT0 | div | 20: DIVx h4.xy, h2.xz--, h2.ww--; + | SCT1 | mov | 21: MOVr r1.zw, g[TEX0].--xy; + | SCB1 | max | 22: MAXh h2.w, h0, h1; + | | | + 8 | SCT0 | mad | 24: MADr r0.xy,-h2.xz--, const.zw--, r1.zw--; + | SCT1 | mov | 26: TXLr h0, r0, const.xxxx, TEX0; + | TEX | txl | 26: TXLr h0, r0, const.xxxx, TEX0; + | SCB0 | max | 28: MAXh h5.x, h2.w---, h5; + | SCB1 | min | 29: MINh h5.w, h5.---y, h4; + | | | + 9 | SCT0 | mad | 30: MADr r1.xy, h2.xz--, const.zw--, r1.zw--; + | SCT1 | mov | 32: TXLr h2, r1, const.xxxx, TEX0; + | TEX | txl | 32: TXLr h2, r1, const.xxxx, TEX0; + | SCB0/1 | add | 34: ADDh/2 h2, h0, h2; + | | | + 10 | SCT0/1 | mov | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; + | TEX | txl | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; + | SCB0 | max | 37: MAXh h5.y, h5.-x--, h1.-w--; + | SCB1 | min | 38: MINh h4.w, h1, h5; + | | | + 11 | SCT0 | mad | 39: MADr r0.xy,-h4, const.xy--, r1.zw--; + | SCT1 | mov | 41: TXLr h0, r0, const.zzzz, TEX0; + | TEX | txl | 41: TXLr h0, r0, const.zzzz, TEX0; + | SCB0 | mad | 44: MADr r2.xy, h4, const.xy--, r1.zw--; + | SCB1 | add | 43: ADDh*8 h5.z, h5.--y-,-h4.--w-; + | | | + 12 | SCT0/1 | mov | 46: TXLr h3, r2, const.xxxx, TEX0; + | TEX | txl | 46: TXLr h3, r2, const.xxxx, TEX0; + | SCB0/1 | add | 48: ADDh/2 h0, h0, h3; + | | | + 13 | SCT0/1 | mad | 49: ADDh/2 h3, h0, h2; + | SCB0/1 | mul | 50: MOVh h0, h3; + | | | + 14 | SCT0 | set | 51: SLTh h3.x, h3.w---, h5.w---; + | SCT1 | set | 52: SGTh h3.w, h3, h5.---x; + | SCB0 | set | 54: SLThc0 rc, h5.z---, h5; + | SCB1 | add | 53: ADDxc0_s rc, h3.---x, h3; + | | | + 15 | SCT0/1 | mul | 55: MOVh h0(NE0.wwww), h2; + | SCB0/1 | mul | 56: MOVh h0(NE0.xxxx), h1; + +Pass SCT TEX SCB + 1: 0% 100% 25% + 2: 0% 100% 25% + 3: 0% 100% 50% + 4: 0% 100% 50% + 5: 50% 0% 25% + 6: 0% 0% 25% + 7: 100% 0% 25% + 8: 0% 100% 50% + 9: 0% 100% 100% + 10: 0% 100% 50% + 11: 0% 100% 75% + 12: 0% 100% 100% + 13: 100% 0% 100% + 14: 50% 0% 50% + 15: 100% 0% 100% + +MEAN: 26% 60% 56% + +Pass SCT0 SCT1 TEX SCB0 SCB1 + 1: 0% 0% 100% 100% 0% + 2: 0% 0% 100% 100% 0% + 3: 0% 0% 100% 100% 100% + 4: 0% 0% 100% 100% 100% + 5: 100% 100% 0% 100% 0% + 6: 0% 0% 0% 0% 100% + 7: 100% 100% 0% 0% 100% + 8: 0% 0% 100% 100% 100% + 9: 0% 0% 100% 100% 100% + 10: 0% 0% 100% 100% 100% + 11: 0% 0% 100% 100% 100% + 12: 0% 0% 100% 100% 100% + 13: 100% 100% 0% 100% 100% + 14: 100% 100% 0% 100% 100% + 15: 100% 100% 0% 100% 100% + +MEAN: 33% 33% 60% 86% 80% +Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 +Results 15 cycles, 3 r regs, 800,000,000 pixels/s +============================================================================*/ +#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 1) +/*--------------------------------------------------------------------------*/ +#pragma regcount 7 +#pragma disablepc all +#pragma option O2 +#pragma option OutColorPrec=fp16 +#pragma texformat default RGBA8 +/*==========================================================================*/ +half4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ +// (1) + half4 rgbyNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaNe = rgbyNe.w + half(1.0/512.0); + #else + half lumaNe = rgbyNe.y + half(1.0/512.0); + #endif +/*--------------------------------------------------------------------------*/ +// (2) + half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaSwNegNe = lumaSw.w - lumaNe; + #else + half lumaSwNegNe = lumaSw.y - lumaNe; + #endif +/*--------------------------------------------------------------------------*/ +// (3) + half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxNwSw = max(lumaNw.w, lumaSw.w); + half lumaMinNwSw = min(lumaNw.w, lumaSw.w); + #else + half lumaMaxNwSw = max(lumaNw.y, lumaSw.y); + half lumaMinNwSw = min(lumaNw.y, lumaSw.y); + #endif +/*--------------------------------------------------------------------------*/ +// (4) + half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half dirZ = lumaNw.w + lumaSwNegNe; + half dirX = -lumaNw.w + lumaSwNegNe; + #else + half dirZ = lumaNw.y + lumaSwNegNe; + half dirX = -lumaNw.y + lumaSwNegNe; + #endif +/*--------------------------------------------------------------------------*/ +// (5) + half3 dir; + dir.y = 0.0; + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x = lumaSe.w + dirX; + dir.z = -lumaSe.w + dirZ; + half lumaMinNeSe = min(lumaNe, lumaSe.w); + #else + dir.x = lumaSe.y + dirX; + dir.z = -lumaSe.y + dirZ; + half lumaMinNeSe = min(lumaNe, lumaSe.y); + #endif +/*--------------------------------------------------------------------------*/ +// (6) + half4 dir1_pos; + dir1_pos.xy = normalize(dir).xz; + half dirAbsMinTimes8 = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS); +/*--------------------------------------------------------------------------*/ +// (7) + half4 dir2_pos; + dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimes8, half(-2.0), half(2.0)); + dir1_pos.zw = pos.xy; + dir2_pos.zw = pos.xy; + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxNeSe = max(lumaNe, lumaSe.w); + #else + half lumaMaxNeSe = max(lumaNe, lumaSe.y); + #endif +/*--------------------------------------------------------------------------*/ +// (8) + half4 temp1N; + temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; + temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); + half lumaMax = max(lumaMaxNwSw, lumaMaxNeSe); + half lumaMin = min(lumaMinNwSw, lumaMinNeSe); +/*--------------------------------------------------------------------------*/ +// (9) + half4 rgby1; + rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; + rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); + rgby1 = (temp1N + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (10) + half4 rgbyM = h4tex2Dlod(tex, half4(pos.xy, 0.0, 0.0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxM = max(lumaMax, rgbyM.w); + half lumaMinM = min(lumaMin, rgbyM.w); + #else + half lumaMaxM = max(lumaMax, rgbyM.y); + half lumaMinM = min(lumaMin, rgbyM.y); + #endif +/*--------------------------------------------------------------------------*/ +// (11) + half4 temp2N; + temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); + half4 rgby2; + rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + half lumaRangeM = (lumaMaxM - lumaMinM) / FXAA_CONSOLE_X_PS3_EDGE_THRESHOLD; +/*--------------------------------------------------------------------------*/ +// (12) + rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); + rgby2 = (temp2N + rgby2) * 0.5; +/*--------------------------------------------------------------------------*/ +// (13) + rgby2 = (rgby2 + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (14) + #if (FXAA_GREEN_AS_LUMA == 0) + bool twoTapLt = rgby2.w < lumaMin; + bool twoTapGt = rgby2.w > lumaMax; + #else + bool twoTapLt = rgby2.y < lumaMin; + bool twoTapGt = rgby2.y > lumaMax; + #endif + bool earlyExit = lumaRangeM < lumaMax; + bool twoTap = twoTapLt || twoTapGt; +/*--------------------------------------------------------------------------*/ +// (15) + if(twoTap) rgby2 = rgby1; + if(earlyExit) rgby2 = rgbyM; +/*--------------------------------------------------------------------------*/ + return rgby2; } +/*==========================================================================*/ +#endif + + +#else +#define FXAA_SPAN_MAX 8.0 +#define FXAA_REDUCE_MUL 1.0/8.0 +#define FXAA_REDUCE_MIN 1.0/128.0 + +vec4 FxaaPixelShader( + vec2 pos, + vec4 fxaaConsolePosPos, + sampler2D tex, + sampler2D fxaaConsole360TexExpBiasNegOne, + sampler2D fxaaConsole360TexExpBiasNegTwo, + vec2 fxaaQualityRcpFrame, + vec4 fxaaConsoleRcpFrameOpt, + vec4 fxaaConsoleRcpFrameOpt2, + vec4 fxaaConsole360RcpFrameOpt2, + float fxaaQualitySubpix, + float fxaaQualityEdgeThreshold, + float fxaaQualityEdgeThresholdMin, + float fxaaConsoleEdgeSharpness, + float fxaaConsoleEdgeThreshold, + float fxaaConsoleEdgeThresholdMin, + vec4 fxaaConsole360ConstDir +) { +#define Tex() qf_texture(tex, pos).rgb +#define TexOfs(ofs) qf_texture(tex, pos + ofs).rgb +#define TexOfsInv(ofs) qf_texture(tex, pos + ofs * fxaaQualityRcpFrame).rgb + + vec3 rgbNW = TexOfsInv(vec2(-1.0,-1.0)); + vec3 rgbNE = TexOfsInv(vec2(1.0,-1.0)); + vec3 rgbSW = TexOfsInv(vec2(-1.0,1.0)); + vec3 rgbSE = TexOfsInv(vec2(1.0,1.0)); + vec3 rgbM = Tex(); + + vec3 luma = vec3(0.299, 0.587, 0.114); + float lumaNW = dot(rgbNW, luma); + float lumaNE = dot(rgbNE, luma); + float lumaSW = dot(rgbSW, luma); + float lumaSE = dot(rgbSE, luma); + float lumaM = dot(rgbM, luma); + + float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); + float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); + + vec2 dir; + dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); + dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); + + float dirReduce = max( + (lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), + FXAA_REDUCE_MIN); + float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce); + + dir = min(vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX), + max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), + dir * rcpDirMin)) * fxaaQualityRcpFrame; + + vec3 rgbA = (1.0/2.0) * ( + TexOfs(dir * (1.0/3.0 - 0.5)) + + TexOfs(dir * (2.0/3.0 - 0.5))); + vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * ( + TexOfs(dir * (0.0/3.0 - 0.5)) + + TexOfs(dir * (3.0/3.0 - 0.5))); + float lumaB = dot(rgbB, luma); + + if((lumaB < lumaMin) || (lumaB > lumaMax)){ + return vec4(rgbA, 1.0); + }else{ + return vec4(rgbB, 1.0); + } +} + + +#endif + +void main(void) +{ + // Only used on FXAA Quality. + // Choose the amount of sub-pixel aliasing removal. + // This can effect sharpness. + // 1.00 - upper limit (softer) + // 0.75 - default amount of filtering + // 0.50 - lower limit (sharper, less sub-pixel aliasing removal) + // 0.25 - almost off + // 0.00 - completely off + float QualitySubpix = 0.75; + + // The minimum amount of local contrast required to apply algorithm. + // 0.333 - too little (faster) + // 0.250 - low quality + // 0.166 - default + // 0.125 - high quality + // 0.033 - very high quality (slower) + float QualityEdgeThreshold = 0.166; + float QualityEdgeThresholdMin = 0.0; + + vec4 ConsolePosPos = vec4(0.0,0.0,0.0,0.0); + vec4 ConsoleRcpFrameOpt = vec4(0.0,0.0,0.0,0.0); + vec4 ConsoleRcpFrameOpt2 = vec4(0.0,0.0,0.0,0.0); + vec4 Console360RcpFrameOpt2 = vec4(0.0,0.0,0.0,0.0); + float ConsoleEdgeSharpness = 8.0; + float ConsoleEdgeThreshold = 0.125; + float ConsoleEdgeThresholdMin = 0.05; + vec4 Console360ConstDir = vec4(1.0, -1.0, 0.25, -0.25); + + qf_FragColor = FxaaPixelShader(v_TexCoord, ConsolePosPos, u_BaseTexture, u_BaseTexture, u_BaseTexture, + u_TextureParams.zw, ConsoleRcpFrameOpt, ConsoleRcpFrameOpt2, Console360RcpFrameOpt2, + QualitySubpix, QualityEdgeThreshold, QualityEdgeThresholdMin, ConsoleEdgeSharpness, + ConsoleEdgeThreshold, ConsoleEdgeThresholdMin, Console360ConstDir); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +qf_varying vec2 v_TexCoord; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +void main(void) +{ + gl_Position = u_ModelViewProjectionMatrix * a_Position; + v_TexCoord = a_TexCoord; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#define FXAA_PC 1 +#if QF_GLSL_VERSION >= 130 +# define FXAA_GLSL_130 1 +#else +# define FXAA_GLSL_120 1 +#endif +# ifdef GL_ARB_gpu_shader5 +# extension GL_ARB_gpu_shader5 : enable +# endif +#define FXAA_GREEN_AS_LUMA 1 +#define FXAA_QUALITY_X_PRESET 23 + +uniform sampler2D u_BaseTexture; + +#ifdef GL_ARB_gpu_shader5 +/*============================================================================ + + + NVIDIA FXAA 3.11 by TIMOTHY LOTTES + + +------------------------------------------------------------------------------ +COPYRIGHT (C) 2010, 2011 NVIDIA CORPORATION. ALL RIGHTS RESERVED. +------------------------------------------------------------------------------ +TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED +*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA +OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR +CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR +LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, +OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE +THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +------------------------------------------------------------------------------ + INTEGRATION CHECKLIST +------------------------------------------------------------------------------ +(1.) +In the shader source, setup defines for the desired configuration. +When providing multiple shaders (for different presets), +simply setup the defines differently in multiple files. +Example, + + #define FXAA_PC 1 + #define FXAA_HLSL_5 1 + #define FXAA_QUALITY_X_PRESET 12 + +Or, + + #define FXAA_360 1 + +Or, + + #define FXAA_PS3 1 + +Etc. + +(2.) +Then include this file, + + #include "Fxaa3_11.h" + +(3.) +Then call the FXAA pixel shader from within your desired shader. +Look at the FXAA Quality FxaaPixelShader() for docs on inputs. +As for FXAA 3.11 all inputs for all shaders are the same +to enable easy porting between platforms. + + return FxaaPixelShader(...); + +(4.) +Insure pass prior to FXAA outputs RGBL (see next section). +Or use, + + #define FXAA_GREEN_AS_LUMA 1 + +(5.) +Setup engine to provide the following constants +which are used in the FxaaPixelShader() inputs, + + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir + +Look at the FXAA Quality FxaaPixelShader() for docs on inputs. + +(6.) +Have FXAA vertex shader run as a full screen triangle, +and output "pos" and "fxaaConsolePosPos" +such that inputs in the pixel shader provide, + + // {xy} = center of pixel + FxaaFloat2 pos, + + // {xy_X_} = upper left of pixel + // {_X_zw} = lower right of pixel + FxaaFloat4 fxaaConsolePosPos, + +(7.) +Insure the texture sampler(s) used by FXAA are set to bilinear filtering. + + +------------------------------------------------------------------------------ + INTEGRATION - RGBL AND COLORSPACE +------------------------------------------------------------------------------ +FXAA3 requires RGBL as input unless the following is set, + + #define FXAA_GREEN_AS_LUMA 1 + +In which case the engine uses green in place of luma, +and requires RGB input is in a non-linear colorspace. + +RGB should be LDR (low dynamic range). +Specifically do FXAA after tonemapping. + +RGB data as returned by a texture fetch can be non-linear, +or linear when FXAA_GREEN_AS_LUMA is not set. +Note an "sRGB format" texture counts as linear, +because the result of a texture fetch is linear data. +Regular "RGBA8" textures in the sRGB colorspace are non-linear. + +If FXAA_GREEN_AS_LUMA is not set, +luma must be stored in the alpha channel prior to running FXAA. +This luma should be in a perceptual space (could be gamma 2.0). +Example pass before FXAA where output is gamma 2.0 encoded, + + color.rgb = ToneMap(color.rgb); // linear color output + color.rgb = sqrt(color.rgb); // gamma 2.0 color output + return color; + +To use FXAA, + + color.rgb = ToneMap(color.rgb); // linear color output + color.rgb = sqrt(color.rgb); // gamma 2.0 color output + color.a = dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114)); // compute luma + return color; + +Another example where output is linear encoded, +say for instance writing to an sRGB formated render target, +where the render target does the conversion back to sRGB after blending, + + color.rgb = ToneMap(color.rgb); // linear color output + return color; + +To use FXAA, + + color.rgb = ToneMap(color.rgb); // linear color output + color.a = sqrt(dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114))); // compute luma + return color; + +Getting luma correct is required for the algorithm to work correctly. + + +------------------------------------------------------------------------------ + BEING LINEARLY CORRECT? +------------------------------------------------------------------------------ +Applying FXAA to a framebuffer with linear RGB color will look worse. +This is very counter intuitive, but happends to be true in this case. +The reason is because dithering artifacts will be more visiable +in a linear colorspace. + + +------------------------------------------------------------------------------ + COMPLEX INTEGRATION +------------------------------------------------------------------------------ +Q. What if the engine is blending into RGB before wanting to run FXAA? + +A. In the last opaque pass prior to FXAA, + have the pass write out luma into alpha. + Then blend into RGB only. + FXAA should be able to run ok + assuming the blending pass did not any add aliasing. + This should be the common case for particles and common blending passes. + +A. Or use FXAA_GREEN_AS_LUMA. + +============================================================================*/ + +/*============================================================================ + + INTEGRATION KNOBS + +============================================================================*/ +// +// FXAA_PS3 and FXAA_360 choose the console algorithm (FXAA3 CONSOLE). +// FXAA_360_OPT is a prototype for the new optimized 360 version. +// +// 1 = Use API. +// 0 = Don't use API. +// +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_PS3 + #define FXAA_PS3 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_360 + #define FXAA_360 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_360_OPT + #define FXAA_360_OPT 0 +#endif +/*==========================================================================*/ +#ifndef FXAA_PC + // + // FXAA Quality + // The high quality PC algorithm. + // + #define FXAA_PC 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_PC_CONSOLE + // + // The console algorithm for PC is included + // for developers targeting really low spec machines. + // Likely better to just run FXAA_PC, and use a really low preset. + // + #define FXAA_PC_CONSOLE 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GLSL_120 + #define FXAA_GLSL_120 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GLSL_130 + #define FXAA_GLSL_130 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_3 + #define FXAA_HLSL_3 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_4 + #define FXAA_HLSL_4 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_5 + #define FXAA_HLSL_5 0 +#endif +/*==========================================================================*/ +#ifndef FXAA_GREEN_AS_LUMA + // + // For those using non-linear color, + // and either not able to get luma in alpha, or not wanting to, + // this enables FXAA to run using green as a proxy for luma. + // So with this enabled, no need to pack luma in alpha. + // + // This will turn off AA on anything which lacks some amount of green. + // Pure red and blue or combination of only R and B, will get no AA. + // + // Might want to lower the settings for both, + // fxaaConsoleEdgeThresholdMin + // fxaaQualityEdgeThresholdMin + // In order to insure AA does not get turned off on colors + // which contain a minor amount of green. + // + // 1 = On. + // 0 = Off. + // + #define FXAA_GREEN_AS_LUMA 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_EARLY_EXIT + // + // Controls algorithm's early exit path. + // On PS3 turning this ON adds 2 cycles to the shader. + // On 360 turning this OFF adds 10ths of a millisecond to the shader. + // Turning this off on console will result in a more blurry image. + // So this defaults to on. + // + // 1 = On. + // 0 = Off. + // + #define FXAA_EARLY_EXIT 1 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_DISCARD + // + // Only valid for PC OpenGL currently. + // Probably will not work when FXAA_GREEN_AS_LUMA = 1. + // + // 1 = Use discard on pixels which don't need AA. + // For APIs which enable concurrent TEX+ROP from same surface. + // 0 = Return unchanged color on pixels which don't need AA. + // + #define FXAA_DISCARD 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_FAST_PIXEL_OFFSET + // + // Used for GLSL 120 only. + // + // 1 = GL API supports fast pixel offsets + // 0 = do not use fast pixel offsets + // + #ifdef GL_EXT_gpu_shader4 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifdef GL_NV_gpu_shader5 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifdef GL_ARB_gpu_shader5 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifndef FXAA_FAST_PIXEL_OFFSET + #define FXAA_FAST_PIXEL_OFFSET 0 + #endif +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GATHER4_ALPHA + // + // 1 = API supports gather4 on alpha channel. + // 0 = API does not support gather4 on alpha channel. + // + #if (FXAA_HLSL_5 == 1) + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifdef GL_ARB_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifdef GL_NV_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifndef FXAA_GATHER4_ALPHA + #define FXAA_GATHER4_ALPHA 0 + #endif +#endif + +/*============================================================================ + FXAA CONSOLE PS3 - TUNING KNOBS +============================================================================*/ +#ifndef FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS + // + // Consoles the sharpness of edges on PS3 only. + // Non-PS3 tuning is done with shader input. + // + // Due to the PS3 being ALU bound, + // there are only two safe values here: 4 and 8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // + // 8.0 is sharper + // 4.0 is softer + // 2.0 is really soft (good for vector graphics inputs) + // + #if 1 + #define FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS 8.0 + #endif + #if 0 + #define FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS 4.0 + #endif + #if 0 + #define FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS 2.0 + #endif +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_CONSOLE_X_PS3_EDGE_THRESHOLD + // + // Only effects PS3. + // Non-PS3 tuning is done with shader input. + // + // The minimum amount of local contrast required to apply algorithm. + // The console setting has a different mapping than the quality setting. + // + // This only applies when FXAA_EARLY_EXIT is 1. + // + // Due to the PS3 being ALU bound, + // there are only two safe values here: 0.25 and 0.125. + // These options use the shaders ability to a free *|/ by 2|4|8. + // + // 0.125 leaves less aliasing, but is softer + // 0.25 leaves more aliasing, and is sharper + // + #if 1 + #define FXAA_CONSOLE_X_PS3_EDGE_THRESHOLD 0.125 + #else + #define FXAA_CONSOLE_X_PS3_EDGE_THRESHOLD 0.25 + #endif +#endif + +/*============================================================================ + FXAA QUALITY - TUNING KNOBS +------------------------------------------------------------------------------ +NOTE the other tuning knobs are now in the shader function inputs! +============================================================================*/ +#ifndef FXAA_QUALITY_X_PRESET + // + // Choose the quality preset. + // This needs to be compiled into the shader as it effects code. + // Best option to include multiple presets is to + // in each shader define the preset, then include this file. + // + // OPTIONS + // ----------------------------------------------------------------------- + // 10 to 15 - default medium dither (10=fastest, 15=highest quality) + // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality) + // 39 - no dither, very expensive + // + // NOTES + // ----------------------------------------------------------------------- + // 12 = slightly faster then FXAA 3.9 and higher edge quality (default) + // 13 = about same speed as FXAA 3.9 and better than 12 + // 23 = closest to FXAA 3.9 visually and performance wise + // _ = the lowest digit is directly related to performance + // _ = the highest digit is directly related to style + // + #define FXAA_QUALITY_X_PRESET 12 +#endif + + +/*============================================================================ + + FXAA QUALITY - PRESETS + +============================================================================*/ + +/*============================================================================ + FXAA QUALITY - MEDIUM DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY_X_PRESET == 10) + #define FXAA_QUALITY_X_PS 3 + #define FXAA_QUALITY_X_P0 1.5 + #define FXAA_QUALITY_X_P1 3.0 + #define FXAA_QUALITY_X_P2 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 11) + #define FXAA_QUALITY_X_PS 4 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 3.0 + #define FXAA_QUALITY_X_P3 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 12) + #define FXAA_QUALITY_X_PS 5 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 4.0 + #define FXAA_QUALITY_X_P4 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 13) + #define FXAA_QUALITY_X_PS 6 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 2.0 + #define FXAA_QUALITY_X_P4 4.0 + #define FXAA_QUALITY_X_P5 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 14) + #define FXAA_QUALITY_X_PS 7 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 2.0 + #define FXAA_QUALITY_X_P4 2.0 + #define FXAA_QUALITY_X_P5 4.0 + #define FXAA_QUALITY_X_P6 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 15) + #define FXAA_QUALITY_X_PS 8 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 2.0 + #define FXAA_QUALITY_X_P4 2.0 + #define FXAA_QUALITY_X_P5 2.0 + #define FXAA_QUALITY_X_P6 4.0 + #define FXAA_QUALITY_X_P7 12.0 +#endif + +/*============================================================================ + FXAA QUALITY - LOW DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY_X_PRESET == 20) + #define FXAA_QUALITY_X_PS 3 + #define FXAA_QUALITY_X_P0 1.5 + #define FXAA_QUALITY_X_P1 2.0 + #define FXAA_QUALITY_X_P2 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 21) + #define FXAA_QUALITY_X_PS 4 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 22) + #define FXAA_QUALITY_X_PS 5 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 2.0 + #define FXAA_QUALITY_X_P4 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 23) + #define FXAA_QUALITY_X_PS 6 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 2.0 + #define FXAA_QUALITY_X_P4 2.0 + #define FXAA_QUALITY_X_P5 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 24) + #define FXAA_QUALITY_X_PS 7 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 2.0 + #define FXAA_QUALITY_X_P4 2.0 + #define FXAA_QUALITY_X_P5 3.0 + #define FXAA_QUALITY_X_P6 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 25) + #define FXAA_QUALITY_X_PS 8 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 2.0 + #define FXAA_QUALITY_X_P4 2.0 + #define FXAA_QUALITY_X_P5 2.0 + #define FXAA_QUALITY_X_P6 4.0 + #define FXAA_QUALITY_X_P7 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 26) + #define FXAA_QUALITY_X_PS 9 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 2.0 + #define FXAA_QUALITY_X_P4 2.0 + #define FXAA_QUALITY_X_P5 2.0 + #define FXAA_QUALITY_X_P6 2.0 + #define FXAA_QUALITY_X_P7 4.0 + #define FXAA_QUALITY_X_P8 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 27) + #define FXAA_QUALITY_X_PS 10 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 2.0 + #define FXAA_QUALITY_X_P4 2.0 + #define FXAA_QUALITY_X_P5 2.0 + #define FXAA_QUALITY_X_P6 2.0 + #define FXAA_QUALITY_X_P7 2.0 + #define FXAA_QUALITY_X_P8 4.0 + #define FXAA_QUALITY_X_P9 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 28) + #define FXAA_QUALITY_X_PS 11 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 2.0 + #define FXAA_QUALITY_X_P4 2.0 + #define FXAA_QUALITY_X_P5 2.0 + #define FXAA_QUALITY_X_P6 2.0 + #define FXAA_QUALITY_X_P7 2.0 + #define FXAA_QUALITY_X_P8 2.0 + #define FXAA_QUALITY_X_P9 4.0 + #define FXAA_QUALITY_X_P10 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY_X_PRESET == 29) + #define FXAA_QUALITY_X_PS 12 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.5 + #define FXAA_QUALITY_X_P2 2.0 + #define FXAA_QUALITY_X_P3 2.0 + #define FXAA_QUALITY_X_P4 2.0 + #define FXAA_QUALITY_X_P5 2.0 + #define FXAA_QUALITY_X_P6 2.0 + #define FXAA_QUALITY_X_P7 2.0 + #define FXAA_QUALITY_X_P8 2.0 + #define FXAA_QUALITY_X_P9 2.0 + #define FXAA_QUALITY_X_P10 4.0 + #define FXAA_QUALITY_X_P11 8.0 +#endif + +/*============================================================================ + FXAA QUALITY - EXTREME QUALITY +============================================================================*/ +#if (FXAA_QUALITY_X_PRESET == 39) + #define FXAA_QUALITY_X_PS 12 + #define FXAA_QUALITY_X_P0 1.0 + #define FXAA_QUALITY_X_P1 1.0 + #define FXAA_QUALITY_X_P2 1.0 + #define FXAA_QUALITY_X_P3 1.0 + #define FXAA_QUALITY_X_P4 1.0 + #define FXAA_QUALITY_X_P5 1.5 + #define FXAA_QUALITY_X_P6 2.0 + #define FXAA_QUALITY_X_P7 2.0 + #define FXAA_QUALITY_X_P8 2.0 + #define FXAA_QUALITY_X_P9 2.0 + #define FXAA_QUALITY_X_P10 4.0 + #define FXAA_QUALITY_X_P11 8.0 +#endif + + + +/*============================================================================ + + API PORTING + +============================================================================*/ +#if (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1) + #define FxaaBool bool + #define FxaaDiscard discard + #define FxaaFloat float + #define FxaaFloat2 vec2 + #define FxaaFloat3 vec3 + #define FxaaFloat4 vec4 + #define FxaaHalf float + #define FxaaHalf2 vec2 + #define FxaaHalf3 vec3 + #define FxaaHalf4 vec4 + #define FxaaInt2 ivec2 + #define FxaaSat(x) clamp(x, 0.0, 1.0) + #define FxaaTex sampler2D +#else + #define FxaaBool bool + #define FxaaDiscard clip(-1) + #define FxaaFloat float + #define FxaaFloat2 float2 + #define FxaaFloat3 float3 + #define FxaaFloat4 float4 + #define FxaaHalf half + #define FxaaHalf2 half2 + #define FxaaHalf3 half3 + #define FxaaHalf4 half4 + #define FxaaSat(x) saturate(x) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_GLSL_120 == 1) + // Requires, + // #version 120 + // And at least, + // #extension GL_EXT_gpu_shader4 : enable + // (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9) + #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0) + #if (FXAA_FAST_PIXEL_OFFSET == 1) + #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o) + #else + #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0) + #endif + #if (FXAA_GATHER4_ALPHA == 1) + // use #extension GL_ARB_gpu_shader5 : enable + #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) + #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) + #define FxaaTexGreen4(t, p) textureGather(t, p, 1) + #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) + #endif +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_GLSL_130 == 1) + // Requires "#version 130" or better + #define FxaaTexTop(t, p) textureLod(t, p, 0.0) + #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o) + #if (FXAA_GATHER4_ALPHA == 1) + // use #extension GL_ARB_gpu_shader5 : enable + #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) + #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) + #define FxaaTexGreen4(t, p) textureGather(t, p, 1) + #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) + #endif +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1) || (FXAA_PS3 == 1) + #define FxaaInt2 float2 + #define FxaaTex sampler2D + #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0)) + #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0)) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_4 == 1) + #define FxaaInt2 int2 + struct FxaaTex { SamplerState smpl; Texture2D tex; }; + #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) + #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_5 == 1) + #define FxaaInt2 int2 + struct FxaaTex { SamplerState smpl; Texture2D tex; }; + #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) + #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) + #define FxaaTexAlpha4(t, p) t.tex.GatherAlpha(t.smpl, p) + #define FxaaTexOffAlpha4(t, p, o) t.tex.GatherAlpha(t.smpl, p, o) + #define FxaaTexGreen4(t, p) t.tex.GatherGreen(t.smpl, p) + #define FxaaTexOffGreen4(t, p, o) t.tex.GatherGreen(t.smpl, p, o) +#endif + + +/*============================================================================ + GREEN AS LUMA OPTION SUPPORT FUNCTION +============================================================================*/ +#if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; } +#else + FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; } +#endif + + + + +/*============================================================================ + + FXAA3 QUALITY - PC + +============================================================================*/ +#if (FXAA_PC == 1) +/*--------------------------------------------------------------------------*/ +FxaaFloat4 FxaaPixelShader( + // + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy} = center of pixel + FxaaFloat2 pos, + // + // Used only for FXAA Console, and not used on the 360 version. + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy_X_} = upper left of pixel + // {_X_zw} = lower right of pixel + FxaaFloat4 fxaaConsolePosPos, + // + // Input color texture. + // {rgb_} = color in linear or perceptual color space + // if (FXAA_GREEN_AS_LUMA == 0) + // {_X__a} = luma in perceptual color space (not linear) + FxaaTex tex, + // + // Only used on the optimized 360 version of FXAA Console. + // For everything but 360, just use the same input here as for "tex". + // For 360, same texture, just alias with a 2nd sampler. + // This sampler needs to have an exponent bias of -1. + FxaaTex fxaaConsole360TexExpBiasNegOne, + // + // Only used on the optimized 360 version of FXAA Console. + // For everything but 360, just use the same input here as for "tex". + // For 360, same texture, just alias with a 3nd sampler. + // This sampler needs to have an exponent bias of -2. + FxaaTex fxaaConsole360TexExpBiasNegTwo, + // + // Only used on FXAA Quality. + // This must be from a constant/uniform. + // {x_} = 1.0/screenWidthInPixels + // {_y} = 1.0/screenHeightInPixels + FxaaFloat2 fxaaQualityRcpFrame, + // + // Only used on FXAA Console. + // This must be from a constant/uniform. + // This effects sub-pixel AA quality and inversely sharpness. + // Where N ranges between, + // N = 0.50 (default) + // N = 0.33 (sharper) + // {x_X__} = -N/screenWidthInPixels + // {_y_X_} = -N/screenHeightInPixels + // {_X_z_} = N/screenWidthInPixels + // {_X__w} = N/screenHeightInPixels + FxaaFloat4 fxaaConsoleRcpFrameOpt, + // + // Only used on FXAA Console. + // Not used on 360, but used on PS3 and PC. + // This must be from a constant/uniform. + // {x_X__} = -2.0/screenWidthInPixels + // {_y_X_} = -2.0/screenHeightInPixels + // {_X_z_} = 2.0/screenWidthInPixels + // {_X__w} = 2.0/screenHeightInPixels + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + // + // Only used on FXAA Console. + // Only used on 360 in place of fxaaConsoleRcpFrameOpt2. + // This must be from a constant/uniform. + // {x_X__} = 8.0/screenWidthInPixels + // {_y_X_} = 8.0/screenHeightInPixels + // {_X_z_} = -4.0/screenWidthInPixels + // {_X__w} = -4.0/screenHeightInPixels + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY_X_SUBPIX define. + // It is here now to allow easier tuning. + // Choose the amount of sub-pixel aliasing removal. + // This can effect sharpness. + // 1.00 - upper limit (softer) + // 0.75 - default amount of filtering + // 0.50 - lower limit (sharper, less sub-pixel aliasing removal) + // 0.25 - almost off + // 0.00 - completely off + FxaaFloat fxaaQualitySubpix, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY_X_EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // The minimum amount of local contrast required to apply algorithm. + // 0.333 - too little (faster) + // 0.250 - low quality + // 0.166 - default + // 0.125 - high quality + // 0.063 - overkill (slower) + FxaaFloat fxaaQualityEdgeThreshold, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY_X_EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // 0.0833 - upper limit (default, the start of visible unfiltered edges) + // 0.0625 - high quality (faster) + // 0.0312 - visible limit (slower) + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + FxaaFloat fxaaQualityEdgeThresholdMin, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE_X_EDGE_SHARPNESS define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS for PS3. + // Due to the PS3 being ALU bound, + // there are only three safe values here: 2 and 4 and 8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // For all other platforms can be a non-power of two. + // 8.0 is sharper (default!!!) + // 4.0 is softer + // 2.0 is really soft (good only for vector graphics inputs) + FxaaFloat fxaaConsoleEdgeSharpness, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE_X_EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE_X_PS3_EDGE_THRESHOLD for PS3. + // Due to the PS3 being ALU bound, + // there are only two safe values here: 1/4 and 1/8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // The console setting has a different mapping than the quality setting. + // Other platforms can use other values. + // 0.125 leaves less aliasing, but is softer (default!!!) + // 0.25 leaves more aliasing, and is sharper + FxaaFloat fxaaConsoleEdgeThreshold, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE_X_EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // The console setting has a different mapping than the quality setting. + // This only applies when FXAA_EARLY_EXIT is 1. + // This does not apply to PS3, + // PS3 was simplified to avoid more shader instructions. + // 0.06 - faster but more aliasing in darks + // 0.05 - default + // 0.04 - slower and less aliasing in darks + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + FxaaFloat fxaaConsoleEdgeThresholdMin, + // + // Extra constants for 360 FXAA Console only. + // Use zeros or anything else for other platforms. + // These must be in physical constant registers and NOT immedates. + // Immedates will result in compiler un-optimizing. + // {xyzw} = float4(1.0, -1.0, 0.25, -0.25) + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posM; + posM.x = pos.x; + posM.y = pos.y; + #if (FXAA_GATHER4_ALPHA == 1) + #if (FXAA_DISCARD == 0) + FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); + #if (FXAA_GREEN_AS_LUMA == 0) + #define lumaM rgbyM.w + #else + #define lumaM rgbyM.y + #endif + #endif + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM); + FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1)); + #else + FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM); + FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1)); + #endif + #if (FXAA_DISCARD == 1) + #define lumaM luma4A.w + #endif + #define lumaE luma4A.z + #define lumaS luma4A.x + #define lumaSE luma4A.y + #define lumaNW luma4B.w + #define lumaN luma4B.z + #define lumaW luma4B.x + #else + FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); + #if (FXAA_GREEN_AS_LUMA == 0) + #define lumaM rgbyM.w + #else + #define lumaM rgbyM.y + #endif + FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy)); + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat maxSM = max(lumaS, lumaM); + FxaaFloat minSM = min(lumaS, lumaM); + FxaaFloat maxESM = max(lumaE, maxSM); + FxaaFloat minESM = min(lumaE, minSM); + FxaaFloat maxWN = max(lumaN, lumaW); + FxaaFloat minWN = min(lumaN, lumaW); + FxaaFloat rangeMax = max(maxWN, maxESM); + FxaaFloat rangeMin = min(minWN, minESM); + FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold; + FxaaFloat range = rangeMax - rangeMin; + FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled); + FxaaBool earlyExit = range < rangeMaxClamped; +/*--------------------------------------------------------------------------*/ + if(earlyExit) + #if (FXAA_DISCARD == 1) + FxaaDiscard; + #else + return rgbyM; + #endif +/*--------------------------------------------------------------------------*/ + #if (FXAA_GATHER4_ALPHA == 0) + FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); + #else + FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNS = lumaN + lumaS; + FxaaFloat lumaWE = lumaW + lumaE; + FxaaFloat subpixRcpRange = 1.0/range; + FxaaFloat subpixNSWE = lumaNS + lumaWE; + FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS; + FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNESE = lumaNE + lumaSE; + FxaaFloat lumaNWNE = lumaNW + lumaNE; + FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE; + FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNWSW = lumaNW + lumaSW; + FxaaFloat lumaSWSE = lumaSW + lumaSE; + FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); + FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); + FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; + FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE; + FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4; + FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4; +/*--------------------------------------------------------------------------*/ + FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE; + FxaaFloat lengthSign = fxaaQualityRcpFrame.x; + FxaaBool horzSpan = edgeHorz >= edgeVert; + FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; +/*--------------------------------------------------------------------------*/ + if(!horzSpan) lumaN = lumaW; + if(!horzSpan) lumaS = lumaE; + if(horzSpan) lengthSign = fxaaQualityRcpFrame.y; + FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM; +/*--------------------------------------------------------------------------*/ + FxaaFloat gradientN = lumaN - lumaM; + FxaaFloat gradientS = lumaS - lumaM; + FxaaFloat lumaNN = lumaN + lumaM; + FxaaFloat lumaSS = lumaS + lumaM; + FxaaBool pairN = abs(gradientN) >= abs(gradientS); + FxaaFloat gradient = max(abs(gradientN), abs(gradientS)); + if(pairN) lengthSign = -lengthSign; + FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posB; + posB.x = posM.x; + posB.y = posM.y; + FxaaFloat2 offNP; + offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x; + offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y; + if(!horzSpan) posB.x += lengthSign * 0.5; + if( horzSpan) posB.y += lengthSign * 0.5; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posN; + posN.x = posB.x - offNP.x * FXAA_QUALITY_X_P0; + posN.y = posB.y - offNP.y * FXAA_QUALITY_X_P0; + FxaaFloat2 posP; + posP.x = posB.x + offNP.x * FXAA_QUALITY_X_P0; + posP.y = posB.y + offNP.y * FXAA_QUALITY_X_P0; + FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0; + FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN)); + FxaaFloat subpixE = subpixC * subpixC; + FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP)); +/*--------------------------------------------------------------------------*/ + if(!pairN) lumaNN = lumaSS; + FxaaFloat gradientScaled = gradient * 1.0/4.0; + FxaaFloat lumaMM = lumaM - lumaNN * 0.5; + FxaaFloat subpixF = subpixD * subpixE; + FxaaBool lumaMLTZero = lumaMM < 0.0; +/*--------------------------------------------------------------------------*/ + lumaEndN -= lumaNN * 0.5; + lumaEndP -= lumaNN * 0.5; + FxaaBool doneN = abs(lumaEndN) >= gradientScaled; + FxaaBool doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P1; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P1; + FxaaBool doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P1; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P1; +/*--------------------------------------------------------------------------*/ + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P2; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P2; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P2; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P2; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_X_PS > 3) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P3; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P3; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P3; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P3; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_X_PS > 4) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P4; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P4; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P4; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P4; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_X_PS > 5) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P5; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P5; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P5; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P5; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_X_PS > 6) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P6; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P6; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P6; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P6; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_X_PS > 7) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P7; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P7; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P7; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P7; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_X_PS > 8) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P8; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P8; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P8; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P8; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_X_PS > 9) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P9; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P9; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P9; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P9; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_X_PS > 10) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P10; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P10; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P10; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P10; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_X_PS > 11) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P11; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P11; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P11; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P11; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_X_PS > 12) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_X_P12; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_X_P12; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_X_P12; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_X_P12; +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } +/*--------------------------------------------------------------------------*/ + FxaaFloat dstN = posM.x - posN.x; + FxaaFloat dstP = posP.x - posM.x; + if(!horzSpan) dstN = posM.y - posN.y; + if(!horzSpan) dstP = posP.y - posM.y; +/*--------------------------------------------------------------------------*/ + FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; + FxaaFloat spanLength = (dstP + dstN); + FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; + FxaaFloat spanLengthRcp = 1.0/spanLength; +/*--------------------------------------------------------------------------*/ + FxaaBool directionN = dstN < dstP; + FxaaFloat dst = min(dstN, dstP); + FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP; + FxaaFloat subpixG = subpixF * subpixF; + FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5; + FxaaFloat subpixH = subpixG * fxaaQualitySubpix; +/*--------------------------------------------------------------------------*/ + FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0; + FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH); + if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; + if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign; + #if (FXAA_DISCARD == 1) + return FxaaTexTop(tex, posM); + #else + return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM); + #endif +} +/*==========================================================================*/ +#endif + + + + +/*============================================================================ + + FXAA3 CONSOLE - PC VERSION + +------------------------------------------------------------------------------ +Instead of using this on PC, I'd suggest just using FXAA Quality with + #define FXAA_QUALITY_X_PRESET 10 +Or + #define FXAA_QUALITY_X_PRESET 20 +Either are higher qualilty and almost as fast as this on modern PC GPUs. +============================================================================*/ +#if (FXAA_PC_CONSOLE == 1) +/*--------------------------------------------------------------------------*/ +FxaaFloat4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xy)); + FxaaFloat lumaSw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xw)); + FxaaFloat lumaNe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zy)); + FxaaFloat lumaSe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zw)); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyM = FxaaTexTop(tex, pos.xy); + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat lumaM = rgbyM.w; + #else + FxaaFloat lumaM = rgbyM.y; + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxNwSw = max(lumaNw, lumaSw); + lumaNe += 1.0/384.0; + FxaaFloat lumaMinNwSw = min(lumaNw, lumaSw); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxNeSe = max(lumaNe, lumaSe); + FxaaFloat lumaMinNeSe = min(lumaNe, lumaSe); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMax = max(lumaMaxNeSe, lumaMaxNwSw); + FxaaFloat lumaMin = min(lumaMinNeSe, lumaMinNwSw); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxScaled = lumaMax * fxaaConsoleEdgeThreshold; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMinM = min(lumaMin, lumaM); + FxaaFloat lumaMaxScaledClamped = max(fxaaConsoleEdgeThresholdMin, lumaMaxScaled); + FxaaFloat lumaMaxM = max(lumaMax, lumaM); + FxaaFloat dirSwMinusNe = lumaSw - lumaNe; + FxaaFloat lumaMaxSubMinM = lumaMaxM - lumaMinM; + FxaaFloat dirSeMinusNw = lumaSe - lumaNw; + if(lumaMaxSubMinM < lumaMaxScaledClamped) return rgbyM; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 dir; + dir.x = dirSwMinusNe + dirSeMinusNw; + dir.y = dirSwMinusNe - dirSeMinusNw; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 dir1 = normalize(dir.xy); + FxaaFloat4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * fxaaConsoleRcpFrameOpt.zw); + FxaaFloat4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * fxaaConsoleRcpFrameOpt.zw); +/*--------------------------------------------------------------------------*/ + FxaaFloat dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * fxaaConsoleEdgeSharpness; + FxaaFloat2 dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2 * fxaaConsoleRcpFrameOpt2.zw); + FxaaFloat4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2 * fxaaConsoleRcpFrameOpt2.zw); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyA = rgbyN1 + rgbyP1; + FxaaFloat4 rgbyB = ((rgbyN2 + rgbyP2) * 0.25) + (rgbyA * 0.25); +/*--------------------------------------------------------------------------*/ + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaBool twoTap = (rgbyB.w < lumaMin) || (rgbyB.w > lumaMax); + #else + FxaaBool twoTap = (rgbyB.y < lumaMin) || (rgbyB.y > lumaMax); + #endif + if(twoTap) rgbyB.xyz = rgbyA.xyz * 0.5; + return rgbyB; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - 360 PIXEL SHADER + +------------------------------------------------------------------------------ +This optimized version thanks to suggestions from Andy Luedke. +Should be fully tex bound in all cases. +As of the FXAA 3.11 release, I have still not tested this code, +however I fixed a bug which was in both FXAA 3.9 and FXAA 3.10. +And note this is replacing the old unoptimized version. +If it does not work, please let me know so I can fix it. +============================================================================*/ +#if (FXAA_360 == 1) +/*--------------------------------------------------------------------------*/ + [reduceTempRegUsage(4)] +float4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + float4 lumaNwNeSwSe; + #if (FXAA_GREEN_AS_LUMA == 0) + asm { + tfetch2D lumaNwNeSwSe.w_X__, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._w_X_, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._X_w_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._X__w, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false + }; + #else + asm { + tfetch2D lumaNwNeSwSe.y_X__, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._y_X_, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._X_y_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._X__y, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false + }; + #endif +/*--------------------------------------------------------------------------*/ + lumaNwNeSwSe.y += 1.0/384.0; + float2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); + float2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); + float lumaMin = min(lumaMinTemp.x, lumaMinTemp.y); + float lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y); +/*--------------------------------------------------------------------------*/ + float4 rgbyM = tex2Dlod(tex, float4(pos.xy, 0.0, 0.0)); + #if (FXAA_GREEN_AS_LUMA == 0) + float lumaMinM = min(lumaMin, rgbyM.w); + float lumaMaxM = max(lumaMax, rgbyM.w); + #else + float lumaMinM = min(lumaMin, rgbyM.y); + float lumaMaxM = max(lumaMax, rgbyM.y); + #endif + if((lumaMaxM - lumaMinM) < max(fxaaConsoleEdgeThresholdMin, lumaMax * fxaaConsoleEdgeThreshold)) return rgbyM; +/*--------------------------------------------------------------------------*/ + float2 dir; + dir.x = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.yyxx); + dir.y = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.xyxy); + dir = normalize(dir); +/*--------------------------------------------------------------------------*/ + float4 dir1 = dir.xyxy * fxaaConsoleRcpFrameOpt.xyzw; +/*--------------------------------------------------------------------------*/ + float4 dir2; + float dirAbsMinTimesC = min(abs(dir.x), abs(dir.y)) * fxaaConsoleEdgeSharpness; + dir2 = saturate(fxaaConsole360ConstDir.zzww * dir.xyxy / dirAbsMinTimesC + 0.5); + dir2 = dir2 * fxaaConsole360RcpFrameOpt2.xyxy + fxaaConsole360RcpFrameOpt2.zwzw; +/*--------------------------------------------------------------------------*/ + float4 rgbyN1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.xy, 0.0, 0.0)); + float4 rgbyP1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.zw, 0.0, 0.0)); + float4 rgbyN2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.xy, 0.0, 0.0)); + float4 rgbyP2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.zw, 0.0, 0.0)); +/*--------------------------------------------------------------------------*/ + float4 rgbyA = rgbyN1 + rgbyP1; + float4 rgbyB = rgbyN2 + rgbyP2 + rgbyA * 0.5; +/*--------------------------------------------------------------------------*/ + float4 rgbyR = ((FxaaLuma(rgbyB) - lumaMax) > 0.0) ? rgbyA : rgbyB; + rgbyR = ((FxaaLuma(rgbyB) - lumaMin) > 0.0) ? rgbyR : rgbyA; + return rgbyR; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (NO EARLY EXIT) + +============================================================================== +The code below does not exactly match the assembly. +I have a feeling that 12 cycles is possible, but was not able to get there. +Might have to increase register count to get full performance. +Note this shader does not use perspective interpolation. + +Use the following cgc options, + + --fenable-bx2 --fastmath --fastprecision --nofloatbindings + +------------------------------------------------------------------------------ + NVSHADERPERF OUTPUT +------------------------------------------------------------------------------ +For reference and to aid in debug, output of NVShaderPerf should match this, + +Shader to schedule: + 0: texpkb h0.w(TRUE), v5.zyxx, #0 + 2: addh h2.z(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x + 4: texpkb h0.w(TRUE), v5.xwxx, #0 + 6: addh h0.z(TRUE), -h2, h0.w + 7: texpkb h1.w(TRUE), v5, #0 + 9: addh h0.x(TRUE), h0.z, -h1.w + 10: addh h3.w(TRUE), h0.z, h1 + 11: texpkb h2.w(TRUE), v5.zwzz, #0 + 13: addh h0.z(TRUE), h3.w, -h2.w + 14: addh h0.x(TRUE), h2.w, h0 + 15: nrmh h1.xz(TRUE), h0_n + 16: minh_m8 h0.x(TRUE), |h1|, |h1.z| + 17: maxh h4.w(TRUE), h0, h1 + 18: divx h2.xy(TRUE), h1_n.xzzw, h0_n + 19: movr r1.zw(TRUE), v4.xxxy + 20: madr r2.xz(TRUE), -h1, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zzww, r1.zzww + 22: minh h5.w(TRUE), h0, h1 + 23: texpkb h0(TRUE), r2.xzxx, #0 + 25: madr r0.zw(TRUE), h1.xzxz, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w), r1 + 27: maxh h4.x(TRUE), h2.z, h2.w + 28: texpkb h1(TRUE), r0.zwzz, #0 + 30: addh_d2 h1(TRUE), h0, h1 + 31: madr r0.xy(TRUE), -h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 33: texpkb h0(TRUE), r0, #0 + 35: minh h4.z(TRUE), h2, h2.w + 36: fenct TRUE + 37: madr r1.xy(TRUE), h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 39: texpkb h2(TRUE), r1, #0 + 41: addh_d2 h0(TRUE), h0, h2 + 42: maxh h2.w(TRUE), h4, h4.x + 43: minh h2.x(TRUE), h5.w, h4.z + 44: addh_d2 h0(TRUE), h0, h1 + 45: slth h2.x(TRUE), h0.w, h2 + 46: sgth h2.w(TRUE), h0, h2 + 47: movh h0(TRUE), h0 + 48: addx.c0 rc(TRUE), h2, h2.w + 49: movh h0(c0.NE.x), h1 + +IPU0 ------ Simplified schedule: -------- +Pass | Unit | uOp | PC: Op +-----+--------+------+------------------------- + 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | SCB1 | add | 2: ADDh h2.z, h0.--w-, const.--x-; + | | | + 2 | SCT0/1 | mov | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; + | TEX | txl | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; + | SCB1 | add | 6: ADDh h0.z,-h2, h0.--w-; + | | | + 3 | SCT0/1 | mov | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; + | TEX | txl | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; + | SCB0 | add | 9: ADDh h0.x, h0.z---,-h1.w---; + | SCB1 | add | 10: ADDh h3.w, h0.---z, h1; + | | | + 4 | SCT0/1 | mov | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | TEX | txl | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | SCB0 | add | 14: ADDh h0.x, h2.w---, h0; + | SCB1 | add | 13: ADDh h0.z, h3.--w-,-h2.--w-; + | | | + 5 | SCT1 | mov | 15: NRMh h1.xz, h0; + | SRB | nrm | 15: NRMh h1.xz, h0; + | SCB0 | min | 16: MINh*8 h0.x, |h1|, |h1.z---|; + | SCB1 | max | 17: MAXh h4.w, h0, h1; + | | | + 6 | SCT0 | div | 18: DIVx h2.xy, h1.xz--, h0; + | SCT1 | mov | 19: MOVr r1.zw, g[TEX0].--xy; + | SCB0 | mad | 20: MADr r2.xz,-h1, const.z-w-, r1.z-w-; + | SCB1 | min | 22: MINh h5.w, h0, h1; + | | | + 7 | SCT0/1 | mov | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; + | TEX | txl | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; + | SCB0 | max | 27: MAXh h4.x, h2.z---, h2.w---; + | SCB1 | mad | 25: MADr r0.zw, h1.--xz, const, r1; + | | | + 8 | SCT0/1 | mov | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; + | TEX | txl | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; + | SCB0/1 | add | 30: ADDh/2 h1, h0, h1; + | | | + 9 | SCT0 | mad | 31: MADr r0.xy,-h2, const.xy--, r1.zw--; + | SCT1 | mov | 33: TXLr h0, r0, const.zzzz, TEX0; + | TEX | txl | 33: TXLr h0, r0, const.zzzz, TEX0; + | SCB1 | min | 35: MINh h4.z, h2, h2.--w-; + | | | + 10 | SCT0 | mad | 37: MADr r1.xy, h2, const.xy--, r1.zw--; + | SCT1 | mov | 39: TXLr h2, r1, const.zzzz, TEX0; + | TEX | txl | 39: TXLr h2, r1, const.zzzz, TEX0; + | SCB0/1 | add | 41: ADDh/2 h0, h0, h2; + | | | + 11 | SCT0 | min | 43: MINh h2.x, h5.w---, h4.z---; + | SCT1 | max | 42: MAXh h2.w, h4, h4.---x; + | SCB0/1 | add | 44: ADDh/2 h0, h0, h1; + | | | + 12 | SCT0 | set | 45: SLTh h2.x, h0.w---, h2; + | SCT1 | set | 46: SGTh h2.w, h0, h2; + | SCB0/1 | mul | 47: MOVh h0, h0; + | | | + 13 | SCT0 | mad | 48: ADDxc0_s rc, h2, h2.w---; + | SCB0/1 | mul | 49: MOVh h0(NE0.xxxx), h1; + +Pass SCT TEX SCB + 1: 0% 100% 25% + 2: 0% 100% 25% + 3: 0% 100% 50% + 4: 0% 100% 50% + 5: 0% 0% 50% + 6: 100% 0% 75% + 7: 0% 100% 75% + 8: 0% 100% 100% + 9: 0% 100% 25% + 10: 0% 100% 100% + 11: 50% 0% 100% + 12: 50% 0% 100% + 13: 25% 0% 100% + +MEAN: 17% 61% 67% + +Pass SCT0 SCT1 TEX SCB0 SCB1 + 1: 0% 0% 100% 0% 100% + 2: 0% 0% 100% 0% 100% + 3: 0% 0% 100% 100% 100% + 4: 0% 0% 100% 100% 100% + 5: 0% 0% 0% 100% 100% + 6: 100% 100% 0% 100% 100% + 7: 0% 0% 100% 100% 100% + 8: 0% 0% 100% 100% 100% + 9: 0% 0% 100% 0% 100% + 10: 0% 0% 100% 100% 100% + 11: 100% 100% 0% 100% 100% + 12: 100% 100% 0% 100% 100% + 13: 100% 0% 0% 100% 100% + +MEAN: 30% 23% 61% 76% 100% +Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 +Results 13 cycles, 3 r regs, 923,076,923 pixels/s +============================================================================*/ +#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 0) +/*--------------------------------------------------------------------------*/ +#pragma regcount 7 +#pragma disablepc all +#pragma option O3 +#pragma option OutColorPrec=fp16 +#pragma texformat default RGBA8 +/*==========================================================================*/ +half4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ +// (1) + half4 dir; + half4 lumaNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + lumaNe.w += half(1.0/512.0); + dir.x = -lumaNe.w; + dir.z = -lumaNe.w; + #else + lumaNe.y += half(1.0/512.0); + dir.x = -lumaNe.y; + dir.z = -lumaNe.y; + #endif +/*--------------------------------------------------------------------------*/ +// (2) + half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x += lumaSw.w; + dir.z += lumaSw.w; + #else + dir.x += lumaSw.y; + dir.z += lumaSw.y; + #endif +/*--------------------------------------------------------------------------*/ +// (3) + half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x -= lumaNw.w; + dir.z += lumaNw.w; + #else + dir.x -= lumaNw.y; + dir.z += lumaNw.y; + #endif +/*--------------------------------------------------------------------------*/ +// (4) + half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x += lumaSe.w; + dir.z -= lumaSe.w; + #else + dir.x += lumaSe.y; + dir.z -= lumaSe.y; + #endif +/*--------------------------------------------------------------------------*/ +// (5) + half4 dir1_pos; + dir1_pos.xy = normalize(dir.xyz).xz; + half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS); +/*--------------------------------------------------------------------------*/ +// (6) + half4 dir2_pos; + dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0)); + dir1_pos.zw = pos.xy; + dir2_pos.zw = pos.xy; + half4 temp1N; + temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; +/*--------------------------------------------------------------------------*/ +// (7) + temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); + half4 rgby1; + rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; +/*--------------------------------------------------------------------------*/ +// (8) + rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); + rgby1 = (temp1N + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (9) + half4 temp2N; + temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); +/*--------------------------------------------------------------------------*/ +// (10) + half4 rgby2; + rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); + rgby2 = (temp2N + rgby2) * 0.5; +/*--------------------------------------------------------------------------*/ +// (11) + // compilier moves these scalar ops up to other cycles + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w)); + half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w)); + #else + half lumaMin = min(min(lumaNw.y, lumaSw.y), min(lumaNe.y, lumaSe.y)); + half lumaMax = max(max(lumaNw.y, lumaSw.y), max(lumaNe.y, lumaSe.y)); + #endif + rgby2 = (rgby2 + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (12) + #if (FXAA_GREEN_AS_LUMA == 0) + bool twoTapLt = rgby2.w < lumaMin; + bool twoTapGt = rgby2.w > lumaMax; + #else + bool twoTapLt = rgby2.y < lumaMin; + bool twoTapGt = rgby2.y > lumaMax; + #endif +/*--------------------------------------------------------------------------*/ +// (13) + if(twoTapLt || twoTapGt) rgby2 = rgby1; +/*--------------------------------------------------------------------------*/ + return rgby2; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (WITH EARLY EXIT) + +============================================================================== +The code mostly matches the assembly. +I have a feeling that 14 cycles is possible, but was not able to get there. +Might have to increase register count to get full performance. +Note this shader does not use perspective interpolation. + +Use the following cgc options, + + --fenable-bx2 --fastmath --fastprecision --nofloatbindings + +Use of FXAA_GREEN_AS_LUMA currently adds a cycle (16 clks). +Will look at fixing this for FXAA 3.12. +------------------------------------------------------------------------------ + NVSHADERPERF OUTPUT +------------------------------------------------------------------------------ +For reference and to aid in debug, output of NVShaderPerf should match this, + +Shader to schedule: + 0: texpkb h0.w(TRUE), v5.zyxx, #0 + 2: addh h2.y(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x + 4: texpkb h1.w(TRUE), v5.xwxx, #0 + 6: addh h0.x(TRUE), h1.w, -h2.y + 7: texpkb h2.w(TRUE), v5.zwzz, #0 + 9: minh h4.w(TRUE), h2.y, h2 + 10: maxh h5.x(TRUE), h2.y, h2.w + 11: texpkb h0.w(TRUE), v5, #0 + 13: addh h3.w(TRUE), -h0, h0.x + 14: addh h0.x(TRUE), h0.w, h0 + 15: addh h0.z(TRUE), -h2.w, h0.x + 16: addh h0.x(TRUE), h2.w, h3.w + 17: minh h5.y(TRUE), h0.w, h1.w + 18: nrmh h2.xz(TRUE), h0_n + 19: minh_m8 h2.w(TRUE), |h2.x|, |h2.z| + 20: divx h4.xy(TRUE), h2_n.xzzw, h2_n.w + 21: movr r1.zw(TRUE), v4.xxxy + 22: maxh h2.w(TRUE), h0, h1 + 23: fenct TRUE + 24: madr r0.xy(TRUE), -h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz + 26: texpkb h0(TRUE), r0, #0 + 28: maxh h5.x(TRUE), h2.w, h5 + 29: minh h5.w(TRUE), h5.y, h4 + 30: madr r1.xy(TRUE), h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz + 32: texpkb h2(TRUE), r1, #0 + 34: addh_d2 h2(TRUE), h0, h2 + 35: texpkb h1(TRUE), v4, #0 + 37: maxh h5.y(TRUE), h5.x, h1.w + 38: minh h4.w(TRUE), h1, h5 + 39: madr r0.xy(TRUE), -h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 41: texpkb h0(TRUE), r0, #0 + 43: addh_m8 h5.z(TRUE), h5.y, -h4.w + 44: madr r2.xy(TRUE), h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 46: texpkb h3(TRUE), r2, #0 + 48: addh_d2 h0(TRUE), h0, h3 + 49: addh_d2 h3(TRUE), h0, h2 + 50: movh h0(TRUE), h3 + 51: slth h3.x(TRUE), h3.w, h5.w + 52: sgth h3.w(TRUE), h3, h5.x + 53: addx.c0 rc(TRUE), h3.x, h3 + 54: slth.c0 rc(TRUE), h5.z, h5 + 55: movh h0(c0.NE.w), h2 + 56: movh h0(c0.NE.x), h1 + +IPU0 ------ Simplified schedule: -------- +Pass | Unit | uOp | PC: Op +-----+--------+------+------------------------- + 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | SCB0 | add | 2: ADDh h2.y, h0.-w--, const.-x--; + | | | + 2 | SCT0/1 | mov | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; + | TEX | txl | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; + | SCB0 | add | 6: ADDh h0.x, h1.w---,-h2.y---; + | | | + 3 | SCT0/1 | mov | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | TEX | txl | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | SCB0 | max | 10: MAXh h5.x, h2.y---, h2.w---; + | SCB1 | min | 9: MINh h4.w, h2.---y, h2; + | | | + 4 | SCT0/1 | mov | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; + | TEX | txl | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; + | SCB0 | add | 14: ADDh h0.x, h0.w---, h0; + | SCB1 | add | 13: ADDh h3.w,-h0, h0.---x; + | | | + 5 | SCT0 | mad | 16: ADDh h0.x, h2.w---, h3.w---; + | SCT1 | mad | 15: ADDh h0.z,-h2.--w-, h0.--x-; + | SCB0 | min | 17: MINh h5.y, h0.-w--, h1.-w--; + | | | + 6 | SCT1 | mov | 18: NRMh h2.xz, h0; + | SRB | nrm | 18: NRMh h2.xz, h0; + | SCB1 | min | 19: MINh*8 h2.w, |h2.---x|, |h2.---z|; + | | | + 7 | SCT0 | div | 20: DIVx h4.xy, h2.xz--, h2.ww--; + | SCT1 | mov | 21: MOVr r1.zw, g[TEX0].--xy; + | SCB1 | max | 22: MAXh h2.w, h0, h1; + | | | + 8 | SCT0 | mad | 24: MADr r0.xy,-h2.xz--, const.zw--, r1.zw--; + | SCT1 | mov | 26: TXLr h0, r0, const.xxxx, TEX0; + | TEX | txl | 26: TXLr h0, r0, const.xxxx, TEX0; + | SCB0 | max | 28: MAXh h5.x, h2.w---, h5; + | SCB1 | min | 29: MINh h5.w, h5.---y, h4; + | | | + 9 | SCT0 | mad | 30: MADr r1.xy, h2.xz--, const.zw--, r1.zw--; + | SCT1 | mov | 32: TXLr h2, r1, const.xxxx, TEX0; + | TEX | txl | 32: TXLr h2, r1, const.xxxx, TEX0; + | SCB0/1 | add | 34: ADDh/2 h2, h0, h2; + | | | + 10 | SCT0/1 | mov | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; + | TEX | txl | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; + | SCB0 | max | 37: MAXh h5.y, h5.-x--, h1.-w--; + | SCB1 | min | 38: MINh h4.w, h1, h5; + | | | + 11 | SCT0 | mad | 39: MADr r0.xy,-h4, const.xy--, r1.zw--; + | SCT1 | mov | 41: TXLr h0, r0, const.zzzz, TEX0; + | TEX | txl | 41: TXLr h0, r0, const.zzzz, TEX0; + | SCB0 | mad | 44: MADr r2.xy, h4, const.xy--, r1.zw--; + | SCB1 | add | 43: ADDh*8 h5.z, h5.--y-,-h4.--w-; + | | | + 12 | SCT0/1 | mov | 46: TXLr h3, r2, const.xxxx, TEX0; + | TEX | txl | 46: TXLr h3, r2, const.xxxx, TEX0; + | SCB0/1 | add | 48: ADDh/2 h0, h0, h3; + | | | + 13 | SCT0/1 | mad | 49: ADDh/2 h3, h0, h2; + | SCB0/1 | mul | 50: MOVh h0, h3; + | | | + 14 | SCT0 | set | 51: SLTh h3.x, h3.w---, h5.w---; + | SCT1 | set | 52: SGTh h3.w, h3, h5.---x; + | SCB0 | set | 54: SLThc0 rc, h5.z---, h5; + | SCB1 | add | 53: ADDxc0_s rc, h3.---x, h3; + | | | + 15 | SCT0/1 | mul | 55: MOVh h0(NE0.wwww), h2; + | SCB0/1 | mul | 56: MOVh h0(NE0.xxxx), h1; + +Pass SCT TEX SCB + 1: 0% 100% 25% + 2: 0% 100% 25% + 3: 0% 100% 50% + 4: 0% 100% 50% + 5: 50% 0% 25% + 6: 0% 0% 25% + 7: 100% 0% 25% + 8: 0% 100% 50% + 9: 0% 100% 100% + 10: 0% 100% 50% + 11: 0% 100% 75% + 12: 0% 100% 100% + 13: 100% 0% 100% + 14: 50% 0% 50% + 15: 100% 0% 100% + +MEAN: 26% 60% 56% + +Pass SCT0 SCT1 TEX SCB0 SCB1 + 1: 0% 0% 100% 100% 0% + 2: 0% 0% 100% 100% 0% + 3: 0% 0% 100% 100% 100% + 4: 0% 0% 100% 100% 100% + 5: 100% 100% 0% 100% 0% + 6: 0% 0% 0% 0% 100% + 7: 100% 100% 0% 0% 100% + 8: 0% 0% 100% 100% 100% + 9: 0% 0% 100% 100% 100% + 10: 0% 0% 100% 100% 100% + 11: 0% 0% 100% 100% 100% + 12: 0% 0% 100% 100% 100% + 13: 100% 100% 0% 100% 100% + 14: 100% 100% 0% 100% 100% + 15: 100% 100% 0% 100% 100% + +MEAN: 33% 33% 60% 86% 80% +Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 +Results 15 cycles, 3 r regs, 800,000,000 pixels/s +============================================================================*/ +#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 1) +/*--------------------------------------------------------------------------*/ +#pragma regcount 7 +#pragma disablepc all +#pragma option O2 +#pragma option OutColorPrec=fp16 +#pragma texformat default RGBA8 +/*==========================================================================*/ +half4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ +// (1) + half4 rgbyNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaNe = rgbyNe.w + half(1.0/512.0); + #else + half lumaNe = rgbyNe.y + half(1.0/512.0); + #endif +/*--------------------------------------------------------------------------*/ +// (2) + half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaSwNegNe = lumaSw.w - lumaNe; + #else + half lumaSwNegNe = lumaSw.y - lumaNe; + #endif +/*--------------------------------------------------------------------------*/ +// (3) + half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxNwSw = max(lumaNw.w, lumaSw.w); + half lumaMinNwSw = min(lumaNw.w, lumaSw.w); + #else + half lumaMaxNwSw = max(lumaNw.y, lumaSw.y); + half lumaMinNwSw = min(lumaNw.y, lumaSw.y); + #endif +/*--------------------------------------------------------------------------*/ +// (4) + half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half dirZ = lumaNw.w + lumaSwNegNe; + half dirX = -lumaNw.w + lumaSwNegNe; + #else + half dirZ = lumaNw.y + lumaSwNegNe; + half dirX = -lumaNw.y + lumaSwNegNe; + #endif +/*--------------------------------------------------------------------------*/ +// (5) + half3 dir; + dir.y = 0.0; + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x = lumaSe.w + dirX; + dir.z = -lumaSe.w + dirZ; + half lumaMinNeSe = min(lumaNe, lumaSe.w); + #else + dir.x = lumaSe.y + dirX; + dir.z = -lumaSe.y + dirZ; + half lumaMinNeSe = min(lumaNe, lumaSe.y); + #endif +/*--------------------------------------------------------------------------*/ +// (6) + half4 dir1_pos; + dir1_pos.xy = normalize(dir).xz; + half dirAbsMinTimes8 = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE_X_PS3_EDGE_SHARPNESS); +/*--------------------------------------------------------------------------*/ +// (7) + half4 dir2_pos; + dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimes8, half(-2.0), half(2.0)); + dir1_pos.zw = pos.xy; + dir2_pos.zw = pos.xy; + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxNeSe = max(lumaNe, lumaSe.w); + #else + half lumaMaxNeSe = max(lumaNe, lumaSe.y); + #endif +/*--------------------------------------------------------------------------*/ +// (8) + half4 temp1N; + temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; + temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); + half lumaMax = max(lumaMaxNwSw, lumaMaxNeSe); + half lumaMin = min(lumaMinNwSw, lumaMinNeSe); +/*--------------------------------------------------------------------------*/ +// (9) + half4 rgby1; + rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; + rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); + rgby1 = (temp1N + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (10) + half4 rgbyM = h4tex2Dlod(tex, half4(pos.xy, 0.0, 0.0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxM = max(lumaMax, rgbyM.w); + half lumaMinM = min(lumaMin, rgbyM.w); + #else + half lumaMaxM = max(lumaMax, rgbyM.y); + half lumaMinM = min(lumaMin, rgbyM.y); + #endif +/*--------------------------------------------------------------------------*/ +// (11) + half4 temp2N; + temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); + half4 rgby2; + rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + half lumaRangeM = (lumaMaxM - lumaMinM) / FXAA_CONSOLE_X_PS3_EDGE_THRESHOLD; +/*--------------------------------------------------------------------------*/ +// (12) + rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); + rgby2 = (temp2N + rgby2) * 0.5; +/*--------------------------------------------------------------------------*/ +// (13) + rgby2 = (rgby2 + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (14) + #if (FXAA_GREEN_AS_LUMA == 0) + bool twoTapLt = rgby2.w < lumaMin; + bool twoTapGt = rgby2.w > lumaMax; + #else + bool twoTapLt = rgby2.y < lumaMin; + bool twoTapGt = rgby2.y > lumaMax; + #endif + bool earlyExit = lumaRangeM < lumaMax; + bool twoTap = twoTapLt || twoTapGt; +/*--------------------------------------------------------------------------*/ +// (15) + if(twoTap) rgby2 = rgby1; + if(earlyExit) rgby2 = rgbyM; +/*--------------------------------------------------------------------------*/ + return rgby2; } +/*==========================================================================*/ +#endif + + +#else +#define FXAA_SPAN_MAX 8.0 +#define FXAA_REDUCE_MUL 1.0/8.0 +#define FXAA_REDUCE_MIN 1.0/128.0 + +vec4 FxaaPixelShader( + vec2 pos, + vec4 fxaaConsolePosPos, + sampler2D tex, + sampler2D fxaaConsole360TexExpBiasNegOne, + sampler2D fxaaConsole360TexExpBiasNegTwo, + vec2 fxaaQualityRcpFrame, + vec4 fxaaConsoleRcpFrameOpt, + vec4 fxaaConsoleRcpFrameOpt2, + vec4 fxaaConsole360RcpFrameOpt2, + float fxaaQualitySubpix, + float fxaaQualityEdgeThreshold, + float fxaaQualityEdgeThresholdMin, + float fxaaConsoleEdgeSharpness, + float fxaaConsoleEdgeThreshold, + float fxaaConsoleEdgeThresholdMin, + vec4 fxaaConsole360ConstDir +) { +#define Tex() qf_texture(tex, pos).rgb +#define TexOfs(ofs) qf_texture(tex, pos + ofs).rgb +#define TexOfsInv(ofs) qf_texture(tex, pos + ofs * fxaaQualityRcpFrame).rgb + + vec3 rgbNW = TexOfsInv(vec2(-1.0,-1.0)); + vec3 rgbNE = TexOfsInv(vec2(1.0,-1.0)); + vec3 rgbSW = TexOfsInv(vec2(-1.0,1.0)); + vec3 rgbSE = TexOfsInv(vec2(1.0,1.0)); + vec3 rgbM = Tex(); + + vec3 luma = vec3(0.299, 0.587, 0.114); + float lumaNW = dot(rgbNW, luma); + float lumaNE = dot(rgbNE, luma); + float lumaSW = dot(rgbSW, luma); + float lumaSE = dot(rgbSE, luma); + float lumaM = dot(rgbM, luma); + + float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); + float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); + + vec2 dir; + dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); + dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); + + float dirReduce = max( + (lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), + FXAA_REDUCE_MIN); + float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce); + + dir = min(vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX), + max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), + dir * rcpDirMin)) * fxaaQualityRcpFrame; + + vec3 rgbA = (1.0/2.0) * ( + TexOfs(dir * (1.0/3.0 - 0.5)) + + TexOfs(dir * (2.0/3.0 - 0.5))); + vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * ( + TexOfs(dir * (0.0/3.0 - 0.5)) + + TexOfs(dir * (3.0/3.0 - 0.5))); + float lumaB = dot(rgbB, luma); + + if((lumaB < lumaMin) || (lumaB > lumaMax)){ + return vec4(rgbA, 1.0); + }else{ + return vec4(rgbB, 1.0); + } +} + + +#endif + +void main(void) +{ + // Only used on FXAA Quality. + // Choose the amount of sub-pixel aliasing removal. + // This can effect sharpness. + // 1.00 - upper limit (softer) + // 0.75 - default amount of filtering + // 0.50 - lower limit (sharper, less sub-pixel aliasing removal) + // 0.25 - almost off + // 0.00 - completely off + float QualitySubpix = 0.75; + + // The minimum amount of local contrast required to apply algorithm. + // 0.333 - too little (faster) + // 0.250 - low quality + // 0.166 - default + // 0.125 - high quality + // 0.033 - very high quality (slower) + float QualityEdgeThreshold = 0.166; + float QualityEdgeThresholdMin = 0.0; + + vec4 ConsolePosPos = vec4(0.0,0.0,0.0,0.0); + vec4 ConsoleRcpFrameOpt = vec4(0.0,0.0,0.0,0.0); + vec4 ConsoleRcpFrameOpt2 = vec4(0.0,0.0,0.0,0.0); + vec4 Console360RcpFrameOpt2 = vec4(0.0,0.0,0.0,0.0); + float ConsoleEdgeSharpness = 8.0; + float ConsoleEdgeThreshold = 0.125; + float ConsoleEdgeThresholdMin = 0.05; + vec4 Console360ConstDir = vec4(1.0, -1.0, 0.25, -0.25); + + qf_FragColor = FxaaPixelShader(v_TexCoord, ConsolePosPos, u_BaseTexture, u_BaseTexture, u_BaseTexture, + u_TextureParams.zw, ConsoleRcpFrameOpt, ConsoleRcpFrameOpt2, Console360RcpFrameOpt2, + QualitySubpix, QualityEdgeThreshold, QualityEdgeThresholdMin, ConsoleEdgeSharpness, + ConsoleEdgeThreshold, ConsoleEdgeThresholdMin, Console360ConstDir); +} + +#endif // FRAGMENT_SHADER diff --git a/shaders/warsow/250.shader_test b/shaders/warsow/250.shader_test new file mode 100644 index 0000000..e9cc9e1 --- /dev/null +++ b/shaders/warsow/250.shader_test @@ -0,0 +1,1675 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 2 +#define APPLY_PCF + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) +#endif + + +#ifndef NUM_SHADOWS +#define NUM_SHADOWS 1 +#endif + +qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS]; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS]; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + + for (int i = 0; i < NUM_SHADOWS; i++) + { + v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position; + // a trick whish allows us not to perform the + // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)' + // computation in the fragment shader + v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5; + } +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_RGB_SHADOW +uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy))) +#else +uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) float(qf_shadow(t,v)) +#endif + +uniform float u_ShadowAlpha; +uniform float u_ShadowProjDistance[NUM_SHADOWS]; +uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS]; + +void main(void) +{ + float finalcolor = 1.0; + +#if NUM_SHADOWS >= 1 +#define SHADOW_INDEX 0 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 2 +#define SHADOW_INDEX 1 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 3 +#define SHADOW_INDEX 2 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 4 +#define SHADOW_INDEX 3 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + + qf_FragColor = vec4(vec3(finalcolor),1.0); +} + +#endif // FRAGMENT_SHADER + + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 2 +#define APPLY_PCF + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) +#endif + + +#ifndef NUM_SHADOWS +#define NUM_SHADOWS 1 +#endif + +qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS]; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS]; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + + for (int i = 0; i < NUM_SHADOWS; i++) + { + v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position; + // a trick whish allows us not to perform the + // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)' + // computation in the fragment shader + v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5; + } +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_RGB_SHADOW +uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy))) +#else +uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) float(qf_shadow(t,v)) +#endif + +uniform float u_ShadowAlpha; +uniform float u_ShadowProjDistance[NUM_SHADOWS]; +uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS]; + +void main(void) +{ + float finalcolor = 1.0; + +#if NUM_SHADOWS >= 1 +#define SHADOW_INDEX 0 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 2 +#define SHADOW_INDEX 1 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 3 +#define SHADOW_INDEX 2 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 4 +#define SHADOW_INDEX 3 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + + qf_FragColor = vec4(vec3(finalcolor),1.0); +} + +#endif // FRAGMENT_SHADER + + diff --git a/shaders/warsow/253.shader_test b/shaders/warsow/253.shader_test new file mode 100644 index 0000000..dd16193 --- /dev/null +++ b/shaders/warsow/253.shader_test @@ -0,0 +1,1698 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_PCF +#define NUM_SHADOWS 2 +#define APPLY_DEFORMVERTS + +#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpritePoint; +#else +#define a_SpritePoint vec4(0.0) +#endif + +#if defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpriteRightUpAxis; +#else +#define a_SpriteRightUpAxis vec4(0.0) +#endif + +void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +float t = 0.0; +vec3 dist; +vec3 right, up, forward, newright; + +#if defined(WAVE_SIN) +t = sin(TexCoord.s * 4.000000 + u_QF_ShaderTime * -1.500000); +Position.xyz += max (-1.0 + 1.000000, t) * 7.000000 * Normal.xyz; +#endif +} + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) +#endif + + +#ifndef NUM_SHADOWS +#define NUM_SHADOWS 1 +#endif + +qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS]; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS]; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + + for (int i = 0; i < NUM_SHADOWS; i++) + { + v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position; + // a trick whish allows us not to perform the + // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)' + // computation in the fragment shader + v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5; + } +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_RGB_SHADOW +uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy))) +#else +uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) float(qf_shadow(t,v)) +#endif + +uniform float u_ShadowAlpha; +uniform float u_ShadowProjDistance[NUM_SHADOWS]; +uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS]; + +void main(void) +{ + float finalcolor = 1.0; + +#if NUM_SHADOWS >= 1 +#define SHADOW_INDEX 0 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 2 +#define SHADOW_INDEX 1 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 3 +#define SHADOW_INDEX 2 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 4 +#define SHADOW_INDEX 3 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + + qf_FragColor = vec4(vec3(finalcolor),1.0); +} + +#endif // FRAGMENT_SHADER + + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_PCF +#define NUM_SHADOWS 2 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) +#endif + + +#ifndef NUM_SHADOWS +#define NUM_SHADOWS 1 +#endif + +qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS]; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS]; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + + for (int i = 0; i < NUM_SHADOWS; i++) + { + v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position; + // a trick whish allows us not to perform the + // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)' + // computation in the fragment shader + v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5; + } +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_RGB_SHADOW +uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy))) +#else +uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) float(qf_shadow(t,v)) +#endif + +uniform float u_ShadowAlpha; +uniform float u_ShadowProjDistance[NUM_SHADOWS]; +uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS]; + +void main(void) +{ + float finalcolor = 1.0; + +#if NUM_SHADOWS >= 1 +#define SHADOW_INDEX 0 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 2 +#define SHADOW_INDEX 1 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 3 +#define SHADOW_INDEX 2 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 4 +#define SHADOW_INDEX 3 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + + qf_FragColor = vec4(vec3(finalcolor),1.0); +} + +#endif // FRAGMENT_SHADER diff --git a/shaders/warsow/256.shader_test b/shaders/warsow/256.shader_test new file mode 100644 index 0000000..885e14f --- /dev/null +++ b/shaders/warsow/256.shader_test @@ -0,0 +1,1677 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 4 +#define APPLY_PCF +#define NUM_SHADOWS 2 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) +#endif + + +#ifndef NUM_SHADOWS +#define NUM_SHADOWS 1 +#endif + +qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS]; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS]; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + + for (int i = 0; i < NUM_SHADOWS; i++) + { + v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position; + // a trick whish allows us not to perform the + // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)' + // computation in the fragment shader + v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5; + } +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_RGB_SHADOW +uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy))) +#else +uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) float(qf_shadow(t,v)) +#endif + +uniform float u_ShadowAlpha; +uniform float u_ShadowProjDistance[NUM_SHADOWS]; +uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS]; + +void main(void) +{ + float finalcolor = 1.0; + +#if NUM_SHADOWS >= 1 +#define SHADOW_INDEX 0 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 2 +#define SHADOW_INDEX 1 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 3 +#define SHADOW_INDEX 2 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 4 +#define SHADOW_INDEX 3 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + + qf_FragColor = vec4(vec3(finalcolor),1.0); +} + +#endif // FRAGMENT_SHADER + + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 4 +#define APPLY_PCF +#define NUM_SHADOWS 2 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) +#endif + + +#ifndef NUM_SHADOWS +#define NUM_SHADOWS 1 +#endif + +qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS]; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS]; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + + for (int i = 0; i < NUM_SHADOWS; i++) + { + v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position; + // a trick whish allows us not to perform the + // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)' + // computation in the fragment shader + v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5; + } +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_RGB_SHADOW +uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy))) +#else +uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) float(qf_shadow(t,v)) +#endif + +uniform float u_ShadowAlpha; +uniform float u_ShadowProjDistance[NUM_SHADOWS]; +uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS]; + +void main(void) +{ + float finalcolor = 1.0; + +#if NUM_SHADOWS >= 1 +#define SHADOW_INDEX 0 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 2 +#define SHADOW_INDEX 1 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 3 +#define SHADOW_INDEX 2 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 4 +#define SHADOW_INDEX 3 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + + qf_FragColor = vec4(vec3(finalcolor),1.0); +} + +#endif // FRAGMENT_SHADER + + diff --git a/shaders/warsow/259.shader_test b/shaders/warsow/259.shader_test new file mode 100644 index 0000000..0ec59aa --- /dev/null +++ b/shaders/warsow/259.shader_test @@ -0,0 +1,1675 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 4 +#define APPLY_PCF + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) +#endif + + +#ifndef NUM_SHADOWS +#define NUM_SHADOWS 1 +#endif + +qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS]; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS]; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + + for (int i = 0; i < NUM_SHADOWS; i++) + { + v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position; + // a trick whish allows us not to perform the + // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)' + // computation in the fragment shader + v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5; + } +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_RGB_SHADOW +uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy))) +#else +uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) float(qf_shadow(t,v)) +#endif + +uniform float u_ShadowAlpha; +uniform float u_ShadowProjDistance[NUM_SHADOWS]; +uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS]; + +void main(void) +{ + float finalcolor = 1.0; + +#if NUM_SHADOWS >= 1 +#define SHADOW_INDEX 0 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 2 +#define SHADOW_INDEX 1 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 3 +#define SHADOW_INDEX 2 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 4 +#define SHADOW_INDEX 3 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + + qf_FragColor = vec4(vec3(finalcolor),1.0); +} + +#endif // FRAGMENT_SHADER + + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 4 +#define APPLY_PCF + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) +#endif + + +#ifndef NUM_SHADOWS +#define NUM_SHADOWS 1 +#endif + +qf_varying vec4 v_ShadowProjVector[NUM_SHADOWS]; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +uniform mat4 u_ShadowmapMatrix[NUM_SHADOWS]; + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + + for (int i = 0; i < NUM_SHADOWS; i++) + { + v_ShadowProjVector[i] = u_ShadowmapMatrix[i] * Position; + // a trick whish allows us not to perform the + // 'shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5)' + // computation in the fragment shader + v_ShadowProjVector[i].xyz = (v_ShadowProjVector[i].xyz + vec3(v_ShadowProjVector[i].w)) * 0.5; + } +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_RGB_SHADOW +uniform sampler2D u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) step(v.z, decodedepthmacro(qf_texture(t, v.xy))) +#else +uniform sampler2DShadow u_ShadowmapTexture[NUM_SHADOWS]; +# define dshadow2D(t,v) float(qf_shadow(t,v)) +#endif + +uniform float u_ShadowAlpha; +uniform float u_ShadowProjDistance[NUM_SHADOWS]; +uniform vec4 u_ShadowmapTextureParams[NUM_SHADOWS]; + +void main(void) +{ + float finalcolor = 1.0; + +#if NUM_SHADOWS >= 1 +#define SHADOW_INDEX 0 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 2 +#define SHADOW_INDEX 1 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 3 +#define SHADOW_INDEX 2 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + +#if NUM_SHADOWS >= 4 +#define SHADOW_INDEX 3 + { + vec3 shadowmaptc = vec3(v_ShadowProjVector[SHADOW_INDEX].xyz / v_ShadowProjVector[SHADOW_INDEX].w); + + // this keeps shadows from appearing on surfaces behind frustum's nearplane + float d = step(v_ShadowProjVector[SHADOW_INDEX].w, 0.0); + + //shadowmaptc = (shadowmaptc + vec3 (1.0)) * vec3 (0.5); + shadowmaptc.xy = shadowmaptc.xy * u_ShadowmapTextureParams[SHADOW_INDEX].xy; // .x - texture width + shadowmaptc.z = clamp(shadowmaptc.z, 0.0, 1.0); + shadowmaptc.xy = vec2(clamp(shadowmaptc.x, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].x), clamp(shadowmaptc.y, 0.0, u_ShadowmapTextureParams[SHADOW_INDEX].y)); + + vec2 ShadowMap_TextureScale = u_ShadowmapTextureParams[SHADOW_INDEX].zw; + + float f; + + #ifdef APPLY_DITHER + + # ifdef APPLY_PCF + # define texval(x, y) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) + + // this method can be described as a 'dithered pinwheel' (4 texture lookups) + // which is a combination of the 'pinwheel' filter suggested by eihrul and dithered 4x4 PCF, + // described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + + vec2 offset_dither = mod(floor(gl_FragCoord.xy), 2.0); + offset_dither.y += offset_dither.x; // y ^= x in floating point + offset_dither.y *= step(offset_dither.y, 1.1); + + vec2 center = (shadowmaptc.xy + offset_dither.xy) * ShadowMap_TextureScale; + float group1 = texval(-0.4, 1.0); + float group2 = texval(-1.0, -0.4); + float group3 = texval( 0.4, -1.0); + float group4 = texval( 1.0, 0.4); + + f = dot(vec4(0.25), vec4(group1, group2, group3, group4)); + # else + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)); + # endif // APPLY_PCF + + #else + // an essay by eihrul: + // now think of bilinear filtering as a 1x1 weighted box filter + // that is, it's sampling over a 2x2 area, but only collecting the portion of each pixel it actually steps on + // with a linear shadowmap filter, you are getting that, like normal bilinear sampling + // only its doing the shadowmap test on each pixel first, to generate a new little 2x2 area, then its doing + // the bilinear filtering on that + // so now if you consider your 2x2 filter you have + // each of those taps is actually using linear filtering as you've configured it + // so you are literally sampling almost 16 pixels as is and all you are getting for it is 2x2 + // the trick is to realize that in essence you could instead be sampling a 4x4 area of pixels + // and running a 3x3 weighted box filter on it + // but you would need some way to get the shadowmap to simply return the 4 pixels covered by each + // tap, rather than the filtered result + // which is what the ARB_texture_gather extension is for + // NOTE: we're using emulation of texture_gather now + + # ifdef APPLY_PCF + # define texval(off) dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(off,shadowmaptc.z)) + + vec2 offset = fract(shadowmaptc.xy - 0.5); + vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (shadowmaptc.xy - offset).xyxy)*ShadowMap_TextureScale.xyxy; + f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy))); + + #else + + f = dshadow2D(u_ShadowmapTexture[SHADOW_INDEX], vec3(shadowmaptc.xy * ShadowMap_TextureScale, shadowmaptc.z)); + + #endif // APPLY_PCF + + #endif // APPLY_DITHER + + finalcolor *= clamp(max(max(f, d), u_ShadowAlpha), 0.0, 1.0); + } + +#undef SHADOW_INDEX +#endif + + qf_FragColor = vec4(vec3(finalcolor),1.0); +} + +#endif // FRAGMENT_SHADER + + diff --git a/shaders/warsow/262.shader_test b/shaders/warsow/262.shader_test new file mode 100644 index 0000000..52d7113 --- /dev/null +++ b/shaders/warsow/262.shader_test @@ -0,0 +1,1795 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_AUTOSPRITE2 +#define APPLY_SOFT_PARTICLE +#define APPLY_DEFORMVERTS + +#if defined(APPLY_AUTOSPRITE) || defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpritePoint; +#else +#define a_SpritePoint vec4(0.0) +#endif + +#if defined(APPLY_AUTOSPRITE2) +attribute vec4 a_SpriteRightUpAxis; +#else +#define a_SpriteRightUpAxis vec4(0.0) +#endif + +void QF_DeformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +float t = 0.0; +vec3 dist; +vec3 right, up, forward, newright; + +#if defined(WAVE_SIN) +// local sprite axes +right = QF_LatLong2Norm(a_SpriteRightUpAxis.xy) * u_QF_MirrorSide; +up = QF_LatLong2Norm(a_SpriteRightUpAxis.zw); + +// mid of quad to camera vector +dist = u_QF_ViewOrigin - u_QF_EntityOrigin - a_SpritePoint.xyz; + +// filter any longest-axis-parts off the camera-direction +forward = normalize(dist - up * dot(dist, up)); + +// the right axis vector as it should be to face the camera +newright = cross(up, forward); + +// rotate the quad vertex around the up axis vector +t = dot(right, Position.xyz - a_SpritePoint.xyz); +Position.xyz += t * (newright - right); +Normal.xyz = forward; +#endif +} + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_AUTOSPRITE2 +#define APPLY_SOFT_PARTICLE + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/28.shader_test b/shaders/warsow/28.shader_test new file mode 100644 index 0000000..7031a6f --- /dev/null +++ b/shaders/warsow/28.shader_test @@ -0,0 +1,1031 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +myhalf3 YUV2RGB(vec3 yuv) +{ + // Standard definition TV color matrix + const mat3 yuv2rgb = mat3( + 1.0, 1.0, 1.0, + 0.0, -0.343, -0.711, + 1.400, -0.711, 0.0 + ); + const vec3 yuv_sub = vec3( + 0.0, 0.5, 0.5 + ); + + return clamp( (yuv2rgb * (yuv - yuv_sub)).xyz, 0.0, 1.0 ); +} + +myhalf3 YUV2RGB_HDTV(vec3 yuv) +{ + // High Definition TV color matrix + const mat3 yuv2rgb = mat3( + 1.164, 1.164, 1.164, + 0.0, -0.213, 2.212, + 1.793, -0.533, 0.0 + ); + const vec3 yuv_sub = vec3( + 0.0625, 0.5, 0.5 + ); + + return clamp( (yuv2rgb * (yuv - yuv_sub)).xyz, 0.0, 1.0 ); +} + + +qf_varying vec2 v_TexCoord; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +void main(void) +{ + gl_Position = u_ModelViewProjectionMatrix * a_Position; + v_TexCoord = a_TexCoord; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform sampler2D u_YUVTextureY; +uniform sampler2D u_YUVTextureU; +uniform sampler2D u_YUVTextureV; + +void main(void) +{ + qf_FragColor = vec4(YUV2RGB_HDTV(vec3( + qf_texture(u_YUVTextureY, v_TexCoord).r, + qf_texture(u_YUVTextureU, v_TexCoord).r, + qf_texture(u_YUVTextureV, v_TexCoord).r + )), 1.0); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +myhalf3 YUV2RGB(vec3 yuv) +{ + // Standard definition TV color matrix + const mat3 yuv2rgb = mat3( + 1.0, 1.0, 1.0, + 0.0, -0.343, -0.711, + 1.400, -0.711, 0.0 + ); + const vec3 yuv_sub = vec3( + 0.0, 0.5, 0.5 + ); + + return clamp( (yuv2rgb * (yuv - yuv_sub)).xyz, 0.0, 1.0 ); +} + +myhalf3 YUV2RGB_HDTV(vec3 yuv) +{ + // High Definition TV color matrix + const mat3 yuv2rgb = mat3( + 1.164, 1.164, 1.164, + 0.0, -0.213, 2.212, + 1.793, -0.533, 0.0 + ); + const vec3 yuv_sub = vec3( + 0.0625, 0.5, 0.5 + ); + + return clamp( (yuv2rgb * (yuv - yuv_sub)).xyz, 0.0, 1.0 ); +} + + +qf_varying vec2 v_TexCoord; + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + + +void main(void) +{ + gl_Position = u_ModelViewProjectionMatrix * a_Position; + v_TexCoord = a_TexCoord; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform sampler2D u_YUVTextureY; +uniform sampler2D u_YUVTextureU; +uniform sampler2D u_YUVTextureV; + +void main(void) +{ + qf_FragColor = vec4(YUV2RGB_HDTV(vec3( + qf_texture(u_YUVTextureY, v_TexCoord).r, + qf_texture(u_YUVTextureU, v_TexCoord).r, + qf_texture(u_YUVTextureV, v_TexCoord).r + )), 1.0); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/30.shader_test b/shaders/warsow/30.shader_test deleted file mode 100644 index 04dc676..0000000 --- a/shaders/warsow/30.shader_test +++ /dev/null @@ -1,26 +0,0 @@ -[require] -GLSL >= 1.10 - -[fragment shader] -#version 130 -uniform sampler2D texSampler; -in vec3 texCoords; -out vec4 out_color; - -void main() -{ - out_color = texture(texSampler, texCoords.xy); -} - -[vertex shader] -#version 130 -in vec2 position; -in vec3 textureCoords; -out vec3 texCoords; -void main() -{ - texCoords = textureCoords; - gl_Position = vec4(position, 0.0, 1.0); -} - - diff --git a/shaders/warsow/31.shader_test b/shaders/warsow/31.shader_test index f005219..ce51847 100644 --- a/shaders/warsow/31.shader_test +++ b/shaders/warsow/31.shader_test @@ -1,481 +1,1791 @@ [require] GLSL >= 1.10 +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 1 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + [fragment shader] -#define FRAGMENT_SHADER -// Warsow GLSL shader +#version 130 -#if !defined(__GLSL_CG_DATA_TYPES) +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -void main() +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; -#endif -#endif -#endif -#endif +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; -#endif +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; -#endif +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; -#endif +vec4 DQReal1, DQDual1; +float scale; -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +if (numWeights > 2) { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} } +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -void main() -{ -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#define NUM_BONE_INFLUENCES 1 -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +uniform float u_ShaderTime; -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); -#else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; -#endif +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; -#endif +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors -// deluxemapping using light vectors in modelspace +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; -#ifdef APPLY_LIGHTSTYLE0 +uniform myhalf2 u_BlendMix; -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +uniform float u_MirrorSide; -#define NORMALIZE_DIFFUSE_NORMAL +uniform float u_ZNear, u_ZFar; -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); -#endif +uniform ivec4 u_Viewport; // x, y, width, height -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; -#endif +uniform vec4 u_TextureParams; -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); +uniform myhalf u_SoftParticlesScale; -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) #endif -#endif -#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); -#ifdef APPLY_SPECULAR + falloff *= falloff; -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) #else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); #endif -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); -#else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); #endif -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) +#ifdef APPLY_FOG +struct Fog { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); -} + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) #endif -#else -color = color * myhalf4(gl_Color.rgba); +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); -#else -gl_FragColor = vec4(color); +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif } -#endif // FRAGMENT_SHADER +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); -[vertex shader] -#define VERTEX_SHADER -// Warsow GLSL shader +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} -#if !defined(__GLSL_CG_DATA_TYPES) -#define myhalf float -#define myhalf2 vec2 -#define myhalf3 vec3 -#define myhalf4 vec4 -#else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 #endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; #endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; #endif +qf_varying vec3 v_Position; + #if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +qf_varying vec3 v_EyeVector; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; -#endif +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif #ifdef VERTEX_SHADER -// Vertex shader +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif -uniform vec3 EyeOrigin; +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} -void main() +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) { -gl_FrontColor = gl_Color; - -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) #endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); #endif -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); #endif -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); #endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP #endif } -#endif // VERTEX_SHADER +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); -#ifdef FRAGMENT_SHADER -// Fragment shader + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; + qf_FrontColor = vec4(outColor); -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; #endif -#endif -#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; #endif -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; #ifdef APPLY_DECAL -uniform sampler2D DecalTexture; +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; #endif #if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; +uniform float u_OffsetMappingScale; #endif -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; #endif -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor #if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) // The following reliefmapping and offsetmapping routine was taken from DarkPlaces @@ -483,207 +1793,259 @@ uniform myhalf GlossExponent; // gloss exponent factor vec2 OffsetMapping(vec2 TexCoord) { #ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING } -#endif +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) void main() { #if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; #endif -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; + myhalf3 weightedDiffuseNormalModelspace; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); #ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); #else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; -#endif +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; #endif -// deluxemapping using light vectors in modelspace +#endif // APPLY_CELSHADING -#ifdef APPLY_LIGHTSTYLE0 +#endif // APPLY_DIRECTIONAL_LIGHT -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); #ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); #else - #define NORMALIZE_DIFFUSE_NORMAL - -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); -#endif + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP #ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; -#endif - -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); - -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); - -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); - -#endif -#endif -#endif + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); #endif #ifdef APPLY_SPECULAR #ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); #else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); #endif -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); -#endif + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); #else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); -#endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); #endif +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + #ifdef APPLY_DECAL + #ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); #else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) -{ -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); -} -#endif + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + #else -color = color * myhalf4(gl_Color.rgba); -#endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; #else -gl_FragColor = vec4(color); + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); #endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); } #endif // FRAGMENT_SHADER - diff --git a/shaders/warsow/34.shader_test b/shaders/warsow/34.shader_test index 62d5d00..fb99ed9 100644 --- a/shaders/warsow/34.shader_test +++ b/shaders/warsow/34.shader_test @@ -1,485 +1,1797 @@ [require] GLSL >= 1.10 +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_LIGHTMAPS 1 +#define APPLY_FBLIGHTMAP + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + [fragment shader] -#define FRAGMENT_SHADER -#define APPLY_LIGHTSTYLE0 -#define APPLY_FBLIGHTMAP -// Warsow GLSL shader +#version 130 -#if !defined(__GLSL_CG_DATA_TYPES) +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -void main() +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; -#endif -#endif -#endif -#endif +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; -#endif +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; -#endif +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; -#endif +vec4 DQReal1, DQDual1; +float scale; -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +if (numWeights > 2) { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} } +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -void main() -{ -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + #endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_LIGHTMAPS 1 +#define APPLY_FBLIGHTMAP -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +uniform float u_ShaderTime; -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); -#else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; -#endif +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; -#endif +uniform myhalf2 u_BlendMix; -// deluxemapping using light vectors in modelspace +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) -#ifdef APPLY_LIGHTSTYLE0 +uniform float u_MirrorSide; -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +uniform float u_ZNear, u_ZFar; -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +uniform ivec4 u_Viewport; // x, y, width, height -#define NORMALIZE_DIFFUSE_NORMAL +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) #endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); + falloff *= falloff; -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); + Color += falloff * u_DynamicLights[i].Diffuse; + } -#endif -#endif -#endif -#endif + return Color; +} -#ifdef APPLY_SPECULAR -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) #else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); #endif -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); -#else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); #endif -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) +#ifdef APPLY_FOG +struct Fog { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); -} + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) #endif -#else -color = color * myhalf4(gl_Color.rgba); +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); -#else -gl_FragColor = vec4(color); +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif } -#endif // FRAGMENT_SHADER +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); -[vertex shader] -#define VERTEX_SHADER -#define APPLY_LIGHTSTYLE0 -#define APPLY_FBLIGHTMAP -// Warsow GLSL shader +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} -#if !defined(__GLSL_CG_DATA_TYPES) -#define myhalf float -#define myhalf2 vec2 -#define myhalf3 vec3 -#define myhalf4 vec4 -#else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 #endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; #endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; #endif +qf_varying vec3 v_Position; + #if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +qf_varying vec3 v_EyeVector; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; -#endif +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif #ifdef VERTEX_SHADER -// Vertex shader +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif -uniform vec3 EyeOrigin; +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} -void main() +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) { -gl_FrontColor = gl_Color; - -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) #endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); #endif -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); #endif -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); #endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP #endif } -#endif // VERTEX_SHADER +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); -#ifdef FRAGMENT_SHADER -// Fragment shader + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; + qf_FrontColor = vec4(outColor); -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; #endif -#endif -#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; #endif -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; #ifdef APPLY_DECAL -uniform sampler2D DecalTexture; +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; #endif #if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; +uniform float u_OffsetMappingScale; #endif -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; #endif -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor #if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) // The following reliefmapping and offsetmapping routine was taken from DarkPlaces @@ -487,207 +1799,259 @@ uniform myhalf GlossExponent; // gloss exponent factor vec2 OffsetMapping(vec2 TexCoord) { #ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING } -#endif +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) void main() { #if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; #endif -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; + myhalf3 weightedDiffuseNormalModelspace; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); #ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); #else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; -#endif +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; #endif -// deluxemapping using light vectors in modelspace +#endif // APPLY_CELSHADING -#ifdef APPLY_LIGHTSTYLE0 +#endif // APPLY_DIRECTIONAL_LIGHT -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); #ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); #else - #define NORMALIZE_DIFFUSE_NORMAL - -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); -#endif + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP #ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; -#endif - -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); - -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); - -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); - -#endif -#endif -#endif + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); #endif #ifdef APPLY_SPECULAR #ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); #else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); #endif -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); -#endif + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); #else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); -#endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); #endif +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + #ifdef APPLY_DECAL + #ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); #else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) -{ -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); -} -#endif + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + #else -color = color * myhalf4(gl_Color.rgba); -#endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; #else -gl_FragColor = vec4(color); + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); #endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); } #endif // FRAGMENT_SHADER - diff --git a/shaders/warsow/37.shader_test b/shaders/warsow/37.shader_test index 6e68fc9..04545c1 100644 --- a/shaders/warsow/37.shader_test +++ b/shaders/warsow/37.shader_test @@ -1,487 +1,1799 @@ [require] GLSL >= 1.10 +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_LIGHTMAPS 1 +#define APPLY_FBLIGHTMAP +#define APPLY_SPECULAR + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + [fragment shader] -#define FRAGMENT_SHADER -#define APPLY_LIGHTSTYLE0 -#define APPLY_FBLIGHTMAP -#define APPLY_SPECULAR -// Warsow GLSL shader +#version 130 -#if !defined(__GLSL_CG_DATA_TYPES) +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -void main() +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; -#endif -#endif -#endif -#endif +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; -#endif +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; -#endif +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; -#endif +vec4 DQReal1, DQDual1; +float scale; -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +if (numWeights > 2) { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} } +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -void main() -{ -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_LIGHTMAPS 1 +#define APPLY_FBLIGHTMAP +#define APPLY_SPECULAR -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +uniform float u_ShaderTime; -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); -#else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; -#endif +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; -#endif +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors -// deluxemapping using light vectors in modelspace +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; -#ifdef APPLY_LIGHTSTYLE0 +uniform myhalf2 u_BlendMix; -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +uniform float u_MirrorSide; -#define NORMALIZE_DIFFUSE_NORMAL +uniform float u_ZNear, u_ZFar; -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); -#endif +uniform ivec4 u_Viewport; // x, y, width, height -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; -#endif +uniform vec4 u_TextureParams; -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); +uniform myhalf u_SoftParticlesScale; -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) #endif -#endif -#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); -#ifdef APPLY_SPECULAR + falloff *= falloff; -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) #else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); #endif -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); -#else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); #endif -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) +#ifdef APPLY_FOG +struct Fog { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); -} + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) #endif -#else -color = color * myhalf4(gl_Color.rgba); +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); -#else -gl_FragColor = vec4(color); +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif } -#endif // FRAGMENT_SHADER +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); -[vertex shader] -#define VERTEX_SHADER -#define APPLY_LIGHTSTYLE0 -#define APPLY_FBLIGHTMAP -#define APPLY_SPECULAR -// Warsow GLSL shader +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} -#if !defined(__GLSL_CG_DATA_TYPES) -#define myhalf float -#define myhalf2 vec2 -#define myhalf3 vec3 -#define myhalf4 vec4 -#else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 #endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; #endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; #endif +qf_varying vec3 v_Position; + #if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +qf_varying vec3 v_EyeVector; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; -#endif +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif #ifdef VERTEX_SHADER -// Vertex shader +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif -uniform vec3 EyeOrigin; +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} -void main() +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) { -gl_FrontColor = gl_Color; - -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) #endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); #endif -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); #endif -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); #endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP #endif } -#endif // VERTEX_SHADER +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); -#ifdef FRAGMENT_SHADER -// Fragment shader + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; + qf_FrontColor = vec4(outColor); -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; #endif -#endif -#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; #endif -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; #ifdef APPLY_DECAL -uniform sampler2D DecalTexture; +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; #endif #if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; +uniform float u_OffsetMappingScale; #endif -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; #endif -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor #if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) // The following reliefmapping and offsetmapping routine was taken from DarkPlaces @@ -489,207 +1801,259 @@ uniform myhalf GlossExponent; // gloss exponent factor vec2 OffsetMapping(vec2 TexCoord) { #ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING } -#endif +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) void main() { #if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; #endif -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; + myhalf3 weightedDiffuseNormalModelspace; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); #ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); #else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; -#endif +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; #endif -// deluxemapping using light vectors in modelspace +#endif // APPLY_CELSHADING -#ifdef APPLY_LIGHTSTYLE0 +#endif // APPLY_DIRECTIONAL_LIGHT -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); #ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); #else - #define NORMALIZE_DIFFUSE_NORMAL - -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); -#endif + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP #ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; -#endif - -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); - -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); - -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); - -#endif -#endif -#endif + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); #endif #ifdef APPLY_SPECULAR #ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); #else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); #endif -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); -#endif + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); #else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); -#endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); #endif +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + #ifdef APPLY_DECAL + #ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); #else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) -{ -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); -} -#endif + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + #else -color = color * myhalf4(gl_Color.rgba); -#endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; #else -gl_FragColor = vec4(color); + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); #endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); } #endif // FRAGMENT_SHADER - diff --git a/shaders/warsow/4.shader_test b/shaders/warsow/4.shader_test index 62d5d00..9fdefaf 100644 --- a/shaders/warsow/4.shader_test +++ b/shaders/warsow/4.shader_test @@ -1,693 +1,1271 @@ [require] GLSL >= 1.10 -[fragment shader] -#define FRAGMENT_SHADER -#define APPLY_LIGHTSTYLE0 -#define APPLY_FBLIGHTMAP -// Warsow GLSL shader - -#if !defined(__GLSL_CG_DATA_TYPES) +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 #endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -void main() +if (numWeights > 2) { -gl_FrontColor = gl_Color; +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif -#endif -#endif +} -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + #endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +uniform ivec4 u_Viewport; // x, y, width, height -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +myhalf3 Greyscale(myhalf3 color) { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); } + + +qf_varying vec4 v_TexCoord; +qf_varying vec4 v_ProjVector; +#ifdef APPLY_EYEDOT +qf_varying vec3 v_EyeVector; #endif -void main() +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) { -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); -#else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +#endif -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); -#else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP #endif +} + +#ifdef APPLY_EYEDOT +uniform float u_FrontPlane; #endif -// deluxemapping using light vectors in modelspace +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + myhalf4 inColor = myhalf4(a_Color); -#ifdef APPLY_LIGHTSTYLE0 + TransformVerts(Position, Normal, TexCoord); -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); + qf_FrontColor = vec4(VertexRGBGen(Position, Normal, inColor)); -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else + v_TexCoord.st = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); -#define NORMALIZE_DIFFUSE_NORMAL + vec2 textureMatrix3_[3]; + textureMatrix3_[0] = u_TextureMatrix[0]; + textureMatrix3_[1] = u_TextureMatrix[1]; + textureMatrix3_[2] = -u_TextureMatrix[2]; + v_TexCoord.pq = TextureMatrix2x3Mul(textureMatrix3_, TexCoord); -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); -#endif +#ifdef APPLY_EYEDOT + mat3 v_StrMatrix; + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; + vec3 EyeVectorWorld = (u_ViewOrigin - Position.xyz) * u_FrontPlane; + v_EyeVector = EyeVectorWorld * v_StrMatrix; #endif -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); + gl_Position = u_ModelViewProjectionMatrix * Position; + v_ProjVector = gl_Position; +} -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); +#endif // VERTEX_SHADER -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +#ifdef FRAGMENT_SHADER +// Fragment shader +#ifdef APPLY_DUDV +uniform sampler2D u_DuDvMapTexture; #endif + +#ifdef APPLY_EYEDOT +uniform sampler2D u_NormalmapTexture; #endif -#endif -#endif +uniform sampler2D u_ReflectionTexture; +uniform sampler2D u_RefractionTexture; + +void main(void) +{ + myhalf3 color; -#ifdef APPLY_SPECULAR +#ifdef APPLY_DUDV + vec3 displacement = vec3(qf_texture(u_DuDvMapTexture, vec2(v_TexCoord.pq) * vec2(0.25))); + vec2 coord = vec2(v_TexCoord.st) + vec2(displacement) * vec2 (0.2); -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); + vec3 fdist = vec3 (normalize(vec3(qf_texture(u_DuDvMapTexture, coord)) - vec3 (0.5))) * vec3(0.005); #else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); + vec3 fdist = vec3(0.0); #endif -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); -#endif + // get projective texcoords + float scale = float(1.0 / float(v_ProjVector.w)); + float inv2NW = u_TextureParams.z * 0.5; // .z - inverse width + float inv2NH = u_TextureParams.w * 0.5; // .w - inverse height + vec2 projCoord = (vec2(v_ProjVector.xy) * scale + vec2 (1.0)) * vec2 (0.5) + vec2(fdist.xy); + projCoord.s = float (clamp (float(projCoord.s), inv2NW, 1.0 - inv2NW)); + projCoord.t = float (clamp (float(projCoord.t), inv2NH, 1.0 - inv2NH)); -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); -#else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); + myhalf3 refr = myhalf3(0.0); + myhalf3 refl = myhalf3(0.0); + +#ifdef APPLY_EYEDOT + // calculate dot product between the surface normal and eye vector + // great for simulating qf_varying water translucency based on the view angle + myhalf3 surfaceNormal = normalize(myhalf3(qf_texture(u_NormalmapTexture, coord)) - myhalf3 (0.5)); + vec3 eyeNormal = normalize(myhalf3(v_EyeVector)); + + float refrdot = float(dot(surfaceNormal, eyeNormal)); + //refrdot = float (clamp (refrdot, 0.0, 1.0)); + float refldot = 1.0 - refrdot; + // get refraction and reflection + +#ifdef APPLY_REFRACTION + refr = (myhalf3(qf_texture(u_RefractionTexture, projCoord))) * refrdot; #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); +#ifdef APPLY_REFLECTION + refl = (myhalf3(qf_texture(u_ReflectionTexture, projCoord))) * refldot; #endif -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); #else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) -{ -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); -} + +#ifdef APPLY_REFRACTION + refr = (myhalf3(qf_texture(u_RefractionTexture, projCoord))); #endif +#ifdef APPLY_REFLECTION + refl = (myhalf3(qf_texture(u_ReflectionTexture, projCoord))); +#endif + +#endif // APPLY_EYEDOT + + // add reflection and refraction +#ifdef APPLY_DISTORTION_ALPHA + color = myhalf3(qf_FrontColor.rgb) + myhalf3(mix (refr, refl, myhalf(qf_FrontColor.a))); #else -color = color * myhalf4(gl_Color.rgba); + color = myhalf3(qf_FrontColor.rgb) + refr + refl; #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); +#ifdef APPLY_GREYSCALE + qf_FragColor = vec4(vec3(Greyscale(color)),1.0); #else -gl_FragColor = vec4(color); + qf_FragColor = vec4(vec3(color),1.0); #endif } #endif // FRAGMENT_SHADER +[fragment shader] +#version 130 -[vertex shader] -#define VERTEX_SHADER -#define APPLY_LIGHTSTYLE0 -#define APPLY_FBLIGHTMAP -// Warsow GLSL shader - -#if !defined(__GLSL_CG_DATA_TYPES) +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 #endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -void main() +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif -#endif -#endif +} -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + #endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +uniform ivec4 u_Viewport; // x, y, width, height -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +myhalf3 Greyscale(myhalf3 color) { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); } + + +qf_varying vec4 v_TexCoord; +qf_varying vec4 v_ProjVector; +#ifdef APPLY_EYEDOT +qf_varying vec3 v_EyeVector; #endif -void main() +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) { -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); -#else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +#endif -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); -#else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP #endif +} + +#ifdef APPLY_EYEDOT +uniform float u_FrontPlane; #endif -// deluxemapping using light vectors in modelspace +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + myhalf4 inColor = myhalf4(a_Color); -#ifdef APPLY_LIGHTSTYLE0 + TransformVerts(Position, Normal, TexCoord); -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); + qf_FrontColor = vec4(VertexRGBGen(Position, Normal, inColor)); -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else + v_TexCoord.st = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); -#define NORMALIZE_DIFFUSE_NORMAL + vec2 textureMatrix3_[3]; + textureMatrix3_[0] = u_TextureMatrix[0]; + textureMatrix3_[1] = u_TextureMatrix[1]; + textureMatrix3_[2] = -u_TextureMatrix[2]; + v_TexCoord.pq = TextureMatrix2x3Mul(textureMatrix3_, TexCoord); -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); -#endif +#ifdef APPLY_EYEDOT + mat3 v_StrMatrix; + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; + vec3 EyeVectorWorld = (u_ViewOrigin - Position.xyz) * u_FrontPlane; + v_EyeVector = EyeVectorWorld * v_StrMatrix; #endif -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); + gl_Position = u_ModelViewProjectionMatrix * Position; + v_ProjVector = gl_Position; +} -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); +#endif // VERTEX_SHADER -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +#ifdef FRAGMENT_SHADER +// Fragment shader +#ifdef APPLY_DUDV +uniform sampler2D u_DuDvMapTexture; #endif + +#ifdef APPLY_EYEDOT +uniform sampler2D u_NormalmapTexture; #endif -#endif -#endif +uniform sampler2D u_ReflectionTexture; +uniform sampler2D u_RefractionTexture; + +void main(void) +{ + myhalf3 color; -#ifdef APPLY_SPECULAR +#ifdef APPLY_DUDV + vec3 displacement = vec3(qf_texture(u_DuDvMapTexture, vec2(v_TexCoord.pq) * vec2(0.25))); + vec2 coord = vec2(v_TexCoord.st) + vec2(displacement) * vec2 (0.2); -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); + vec3 fdist = vec3 (normalize(vec3(qf_texture(u_DuDvMapTexture, coord)) - vec3 (0.5))) * vec3(0.005); #else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); + vec3 fdist = vec3(0.0); #endif -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); -#endif + // get projective texcoords + float scale = float(1.0 / float(v_ProjVector.w)); + float inv2NW = u_TextureParams.z * 0.5; // .z - inverse width + float inv2NH = u_TextureParams.w * 0.5; // .w - inverse height + vec2 projCoord = (vec2(v_ProjVector.xy) * scale + vec2 (1.0)) * vec2 (0.5) + vec2(fdist.xy); + projCoord.s = float (clamp (float(projCoord.s), inv2NW, 1.0 - inv2NW)); + projCoord.t = float (clamp (float(projCoord.t), inv2NH, 1.0 - inv2NH)); -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); -#else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); + myhalf3 refr = myhalf3(0.0); + myhalf3 refl = myhalf3(0.0); + +#ifdef APPLY_EYEDOT + // calculate dot product between the surface normal and eye vector + // great for simulating qf_varying water translucency based on the view angle + myhalf3 surfaceNormal = normalize(myhalf3(qf_texture(u_NormalmapTexture, coord)) - myhalf3 (0.5)); + vec3 eyeNormal = normalize(myhalf3(v_EyeVector)); + + float refrdot = float(dot(surfaceNormal, eyeNormal)); + //refrdot = float (clamp (refrdot, 0.0, 1.0)); + float refldot = 1.0 - refrdot; + // get refraction and reflection + +#ifdef APPLY_REFRACTION + refr = (myhalf3(qf_texture(u_RefractionTexture, projCoord))) * refrdot; #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); +#ifdef APPLY_REFLECTION + refl = (myhalf3(qf_texture(u_ReflectionTexture, projCoord))) * refldot; #endif -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); #else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) -{ -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); -} + +#ifdef APPLY_REFRACTION + refr = (myhalf3(qf_texture(u_RefractionTexture, projCoord))); #endif +#ifdef APPLY_REFLECTION + refl = (myhalf3(qf_texture(u_ReflectionTexture, projCoord))); +#endif + +#endif // APPLY_EYEDOT + + // add reflection and refraction +#ifdef APPLY_DISTORTION_ALPHA + color = myhalf3(qf_FrontColor.rgb) + myhalf3(mix (refr, refl, myhalf(qf_FrontColor.a))); #else -color = color * myhalf4(gl_Color.rgba); + color = myhalf3(qf_FrontColor.rgb) + refr + refl; #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); +#ifdef APPLY_GREYSCALE + qf_FragColor = vec4(vec3(Greyscale(color)),1.0); #else -gl_FragColor = vec4(color); + qf_FragColor = vec4(vec3(color),1.0); #endif } #endif // FRAGMENT_SHADER - diff --git a/shaders/warsow/40.shader_test b/shaders/warsow/40.shader_test index de4bd35..1c9c4a9 100644 --- a/shaders/warsow/40.shader_test +++ b/shaders/warsow/40.shader_test @@ -1,697 +1,1751 @@ [require] GLSL >= 1.10 -[fragment shader] -#define FRAGMENT_SHADER -#define APPLY_LIGHTSTYLE0 -#define APPLY_FBLIGHTMAP -#define APPLY_SPECULAR -#define APPLY_AMBIENT_COMPENSATION -// Warsow GLSL shader - -#if !defined(__GLSL_CG_DATA_TYPES) +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 #endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -void main() +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color - -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + #endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) #endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) #else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; + for (int i = 0; i < NUM_DLIGHTS; i++) #endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; } + + +#endif + +#endif #endif -void main() +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif { -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif +} -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); -#else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif +} -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +#endif -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#endif -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +qf_varying vec3 v_Position; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; #else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; #endif +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; #endif -// deluxemapping using light vectors in modelspace +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif -#ifdef APPLY_LIGHTSTYLE0 +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} -#define NORMALIZE_DIFFUSE_NORMAL +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) #endif -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +#endif +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); #endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); #endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP #endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; #endif -#ifdef APPLY_SPECULAR +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); #else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); + FogGen(Position, v_FogCoord); #endif +#endif // APPLY_FOG -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); -#endif + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); #else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; #endif -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; } + +#endif + + +uniform sampler2D u_DepthTexture; + #endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 #else -color = color * myhalf4(gl_Color.rgba); + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); #else -gl_FragColor = vec4(color); + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); #endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); } #endif // FRAGMENT_SHADER +[fragment shader] +#version 130 -[vertex shader] -#define VERTEX_SHADER -#define APPLY_LIGHTSTYLE0 -#define APPLY_FBLIGHTMAP -#define APPLY_SPECULAR -#define APPLY_AMBIENT_COMPENSATION -// Warsow GLSL shader - -#if !defined(__GLSL_CG_DATA_TYPES) +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 #endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; -void main() +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) { -gl_FrontColor = gl_Color; +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color - -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + #endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) #endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor + falloff *= falloff; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) #else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; + for (int i = 0; i < NUM_DLIGHTS; i++) #endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; } + + +#endif + #endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; -void main() +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif { -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif +} -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); -#else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif +} -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +#endif -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#endif -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +qf_varying vec3 v_Position; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; #else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; +qf_varying vec2 v_TexCoord; #endif +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; #endif -// deluxemapping using light vectors in modelspace +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif -#ifdef APPLY_LIGHTSTYLE0 +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#define NORMALIZE_DIFFUSE_NORMAL +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); #endif -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; #endif + #endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); #endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); #endif -#ifdef APPLY_SPECULAR + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); -#else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; #endif -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); #endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); #else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; #endif -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; } + #endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 #else -color = color * myhalf4(gl_Color.rgba); + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); #else -gl_FragColor = vec4(color); + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); #endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); } #endif // FRAGMENT_SHADER - diff --git a/shaders/warsow/43.shader_test b/shaders/warsow/43.shader_test index 4a2358e..1efcfe9 100644 --- a/shaders/warsow/43.shader_test +++ b/shaders/warsow/43.shader_test @@ -1,693 +1,1751 @@ [require] GLSL >= 1.10 -[fragment shader] -#define FRAGMENT_SHADER -#define APPLY_DIRECTIONAL_LIGHT -#define APPLY_CELLSHADING -// Warsow GLSL shader - -#if !defined(__GLSL_CG_DATA_TYPES) +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 #endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -void main() +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color - -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + #endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_CONST + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) #endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) #else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; + for (int i = 0; i < NUM_DLIGHTS; i++) #endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; } + + +#endif + +#endif #endif -void main() +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif { -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif +} -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); -#else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif +} -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +#endif -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#endif -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +qf_varying vec3 v_Position; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; #else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; #endif +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; #endif -// deluxemapping using light vectors in modelspace +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif -#ifdef APPLY_LIGHTSTYLE0 +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} -#define NORMALIZE_DIFFUSE_NORMAL +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) #endif -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +#endif +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); #endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); #endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP #endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; #endif -#ifdef APPLY_SPECULAR +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); #else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); + FogGen(Position, v_FogCoord); #endif +#endif // APPLY_FOG -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); -#endif + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); #else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; #endif -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; } + +#endif + + +uniform sampler2D u_DepthTexture; + #endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 #else -color = color * myhalf4(gl_Color.rgba); + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); #else -gl_FragColor = vec4(color); + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); #endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); } #endif // FRAGMENT_SHADER +[fragment shader] +#version 130 -[vertex shader] -#define VERTEX_SHADER -#define APPLY_DIRECTIONAL_LIGHT -#define APPLY_CELLSHADING -// Warsow GLSL shader - -#if !defined(__GLSL_CG_DATA_TYPES) +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 #endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; -void main() +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) { -gl_FrontColor = gl_Color; +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color - -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + #endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_CONST + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) #endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor + falloff *= falloff; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) #else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; + for (int i = 0; i < NUM_DLIGHTS; i++) #endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; } + + +#endif + #endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; -void main() +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif { -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif +} -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); -#else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif +} -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +#endif -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#endif -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +qf_varying vec3 v_Position; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; #else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; +qf_varying vec2 v_TexCoord; #endif +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; #endif -// deluxemapping using light vectors in modelspace +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif -#ifdef APPLY_LIGHTSTYLE0 +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#define NORMALIZE_DIFFUSE_NORMAL +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); #endif -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; #endif + #endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); #endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); #endif -#ifdef APPLY_SPECULAR + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); -#else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; #endif -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); #endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); #else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; #endif -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; } + #endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 #else -color = color * myhalf4(gl_Color.rgba); + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); #else -gl_FragColor = vec4(color); + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); #endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); } #endif // FRAGMENT_SHADER - diff --git a/shaders/warsow/46.shader_test b/shaders/warsow/46.shader_test index 76c961a..24e5790 100644 --- a/shaders/warsow/46.shader_test +++ b/shaders/warsow/46.shader_test @@ -1,307 +1,1753 @@ [require] GLSL >= 1.10 +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_LIGHTMAPS 1 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + [fragment shader] -#define FRAGMENT_SHADER -// Warsow GLSL shader +#version 130 -#if !defined(__GLSL_CG_DATA_TYPES) +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -varying vec4 TexCoord; -varying vec4 ProjVector; -#ifdef APPLY_EYEDOT -varying vec3 EyeVector; +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) #endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_EYEDOT -uniform vec3 EyeOrigin; -uniform float FrontPlane; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -void main(void) +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -mat4 textureMatrix; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -textureMatrix = gl_TextureMatrix[0]; -TexCoord.st = vec2 (textureMatrix * gl_MultiTexCoord0); +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -textureMatrix = gl_TextureMatrix[0]; -textureMatrix[0] = -textureMatrix[0]; -textureMatrix[1] = -textureMatrix[1]; -TexCoord.pq = vec2 (textureMatrix * gl_MultiTexCoord0); +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; -#ifdef APPLY_EYEDOT -mat3 strMatrix; -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif -vec3 EyeVectorWorld = (EyeOrigin - gl_Vertex.xyz) * FrontPlane; -EyeVector = EyeVectorWorld * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function -gl_Position = ftransform(); -ProjVector = gl_Position; -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} } -#endif // VERTEX_SHADER +float len = length(DQReal); +DQReal /= len; +DQDual /= len; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; -#ifdef FRAGMENT_SHADER -// Fragment shader +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif -#ifdef APPLY_DUDV -uniform sampler2D DuDvMapTexture; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} -#ifdef APPLY_EYEDOT -uniform sampler2D NormalmapTexture; +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -uniform sampler2D ReflectionTexture; -uniform sampler2D RefractionTexture; -uniform float TextureWidth, TextureHeight; +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -void main(void) +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) { -myhalf3 color; +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif -#ifdef APPLY_DUDV -vec3 displacement = vec3(texture2D(DuDvMapTexture, vec2(TexCoord.pq) * vec2(0.25))); -vec2 coord = vec2(TexCoord.st) + vec2(displacement) * vec2 (0.2); +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -vec3 fdist = vec3 (normalize(vec3(texture2D(DuDvMapTexture, coord)) - vec3 (0.5))) * vec3(0.005); +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] #else -vec3 fdist = vec3(0.0); +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + #endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_LIGHTMAPS 1 + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; -// get projective texcoords -float scale = float(1.0 / float(ProjVector.w)); -float inv2NW = 1.0 / (2.0 * float (TextureWidth)); -float inv2NH = 1.0 / (2.0 * float (TextureHeight)); -vec2 projCoord = (vec2(ProjVector.xy) * scale + vec2 (1.0)) * vec2 (0.5) + vec2(fdist.xy); -projCoord.s = float (clamp (float(projCoord.s), inv2NW, 1.0 - inv2NW)); -projCoord.t = float (clamp (float(projCoord.t), inv2NH, 1.0 - inv2NH)); +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; -myhalf3 refr = myhalf3(0.0); -myhalf3 refl = myhalf3(0.0); +uniform myhalf2 u_BlendMix; -#ifdef APPLY_EYEDOT -// calculate dot product between the surface normal and eye vector -// great for simulating varying water translucency based on the view angle -myhalf3 surfaceNormal = normalize(myhalf3(texture2D(NormalmapTexture, coord)) - myhalf3 (0.5)); -vec3 eyeNormal = normalize(myhalf3(EyeVector)); +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) -float refrdot = float(dot(surfaceNormal, eyeNormal)); -//refrdot = float (clamp (refrdot, 0.0, 1.0)); -float refldot = 1.0 - refrdot; -// get refraction and reflection +uniform float u_MirrorSide; -#ifdef APPLY_REFRACTION -refr = (myhalf3(texture2D(RefractionTexture, projCoord))) * refrdot; +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif -#ifdef APPLY_REFLECTION -refl = (myhalf3(texture2D(ReflectionTexture, projCoord))) * refldot; +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) #endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) #else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); -#ifdef APPLY_REFRACTION -refr = (myhalf3(texture2D(RefractionTexture, projCoord))); +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) #endif -#ifdef APPLY_REFLECTION -refl = (myhalf3(texture2D(ReflectionTexture, projCoord))); + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + #endif +#endif #endif -// add reflection and refraction -#ifdef APPLY_DISTORTION_ALPHA -color = myhalf3(gl_Color.rgb) + myhalf3(mix (refr, refl, float(gl_Color.a))); -#else -color = myhalf3(gl_Color.rgb) + refr + refl; +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),1.0); -#else -gl_FragColor = vec4(vec3(color),1.0); +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif } -#endif // FRAGMENT_SHADER +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif -[vertex shader] -#define VERTEX_SHADER -// Warsow GLSL shader +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} -#if !defined(__GLSL_CG_DATA_TYPES) -#define myhalf float -#define myhalf2 vec2 -#define myhalf3 vec3 -#define myhalf4 vec4 +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +qf_varying vec2 v_TexCoord; #endif -varying vec4 TexCoord; -varying vec4 ProjVector; -#ifdef APPLY_EYEDOT -varying vec3 EyeVector; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; #endif -#ifdef VERTEX_SHADER -// Vertex shader +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif -#ifdef APPLY_EYEDOT -uniform vec3 EyeOrigin; -uniform float FrontPlane; +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; #endif -void main(void) +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) { -gl_FrontColor = gl_Color; +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif -mat4 textureMatrix; +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -textureMatrix = gl_TextureMatrix[0]; -TexCoord.st = vec2 (textureMatrix * gl_MultiTexCoord0); +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} -textureMatrix = gl_TextureMatrix[0]; -textureMatrix[0] = -textureMatrix[0]; -textureMatrix[1] = -textureMatrix[1]; -TexCoord.pq = vec2 (textureMatrix * gl_MultiTexCoord0); +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif -#ifdef APPLY_EYEDOT -mat3 strMatrix; -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -vec3 EyeVectorWorld = (EyeOrigin - gl_Vertex.xyz) * FrontPlane; -EyeVector = EyeVectorWorld * strMatrix; +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) #endif -gl_Position = ftransform(); -ProjVector = gl_Position; -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); #endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; #endif -} -#endif // VERTEX_SHADER +#endif +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif -#ifdef FRAGMENT_SHADER -// Fragment shader +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif -#ifdef APPLY_DUDV -uniform sampler2D DuDvMapTexture; + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP #endif +} + -#ifdef APPLY_EYEDOT -uniform sampler2D NormalmapTexture; +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; #endif -uniform sampler2D ReflectionTexture; -uniform sampler2D RefractionTexture; -uniform float TextureWidth, TextureHeight; void main(void) { -myhalf3 color; + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); -#ifdef APPLY_DUDV -vec3 displacement = vec3(texture2D(DuDvMapTexture, vec2(TexCoord.pq) * vec2(0.25))); -vec2 coord = vec2(TexCoord.st) + vec2(displacement) * vec2 (0.2); + TransformVerts(Position, Normal, TexCoord); -vec3 fdist = vec3 (normalize(vec3(texture2D(DuDvMapTexture, coord)) - vec3 (0.5))) * vec3(0.005); + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); #else -vec3 fdist = vec3(0.0); + FogGen(Position, v_FogCoord); #endif +#endif // APPLY_FOG -// get projective texcoords -float scale = float(1.0 / float(ProjVector.w)); -float inv2NW = 1.0 / (2.0 * float (TextureWidth)); -float inv2NH = 1.0 / (2.0 * float (TextureHeight)); -vec2 projCoord = (vec2(ProjVector.xy) * scale + vec2 (1.0)) * vec2 (0.5) + vec2(fdist.xy); -projCoord.s = float (clamp (float(projCoord.s), inv2NW, 1.0 - inv2NW)); -projCoord.t = float (clamp (float(projCoord.t), inv2NH, 1.0 - inv2NH)); + qf_FrontColor = vec4(outColor); +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; -myhalf3 refr = myhalf3(0.0); -myhalf3 refl = myhalf3(0.0); + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); -#ifdef APPLY_EYEDOT -// calculate dot product between the surface normal and eye vector -// great for simulating varying water translucency based on the view angle -myhalf3 surfaceNormal = normalize(myhalf3(texture2D(NormalmapTexture, coord)) - myhalf3 (0.5)); -vec3 eyeNormal = normalize(myhalf3(EyeVector)); + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) -float refrdot = float(dot(surfaceNormal, eyeNormal)); -//refrdot = float (clamp (refrdot, 0.0, 1.0)); -float refldot = 1.0 - refrdot; -// get refraction and reflection + v_Position = Position.xyz; -#ifdef APPLY_REFRACTION -refr = (myhalf3(texture2D(RefractionTexture, projCoord))) * refrdot; -#endif -#ifdef APPLY_REFLECTION -refl = (myhalf3(texture2D(ReflectionTexture, projCoord))) * refldot; +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; #endif +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; #else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif -#ifdef APPLY_REFRACTION -refr = (myhalf3(texture2D(RefractionTexture, projCoord))); +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; #endif -#ifdef APPLY_REFLECTION -refl = (myhalf3(texture2D(ReflectionTexture, projCoord))); + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + #endif + +uniform sampler2D u_DepthTexture; + #endif -// add reflection and refraction -#ifdef APPLY_DISTORTION_ALPHA -color = myhalf3(gl_Color.rgb) + myhalf3(mix (refr, refl, float(gl_Color.a))); +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 #else -color = myhalf3(gl_Color.rgb) + refr + refl; + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),1.0); +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); #else -gl_FragColor = vec4(vec3(color),1.0); + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); #endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); } #endif // FRAGMENT_SHADER - diff --git a/shaders/warsow/49.shader_test b/shaders/warsow/49.shader_test index 9b644bc..b9f25bd 100644 --- a/shaders/warsow/49.shader_test +++ b/shaders/warsow/49.shader_test @@ -1,225 +1,2063 @@ [require] GLSL >= 1.10 +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_LIGHTMAPS 1 +#define APPLY_FBLIGHTMAP +#define APPLY_SPECULAR +#define APPLY_DECAL +#define APPLY_DECAL_ADD + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + [fragment shader] -#define FRAGMENT_SHADER -// Warsow GLSL shader +#version 130 -#if !defined(__GLSL_CG_DATA_TYPES) +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} -varying vec4 ProjVector; +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; -void main(void) +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) { -gl_FrontColor = gl_Color; +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -mat4 textureMatrix; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; -textureMatrix = gl_TextureMatrix[0]; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif -gl_Position = ftransform(); -ProjVector = textureMatrix * gl_Vertex; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif } -#endif // VERTEX_SHADER +// use defines to overload the transform function +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#ifdef FRAGMENT_SHADER -// Fragment shader +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) -uniform myhalf3 LightAmbient; +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -uniform float TextureWidth, TextureHeight; -uniform float ProjDistance; -uniform sampler2DShadow ShadowmapTexture; +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif -void main(void) +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) { -myhalf color = myhalf(1.0); +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} -if (ProjVector.w <= 0.0 || ProjVector.w >= ProjDistance) -discard; +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_LIGHTMAPS 1 +#define APPLY_FBLIGHTMAP +#define APPLY_SPECULAR +#define APPLY_DECAL +#define APPLY_DECAL_ADD + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; -float dtW = 1.0 / TextureWidth; -float dtH = 1.0 / TextureHeight; +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; -vec3 coord = vec3 (ProjVector.xyz / ProjVector.w); -coord = (coord + vec3 (1.0)) * vec3 (0.5); -coord.s = float (clamp (float(coord.s), dtW, 1.0 - dtW)); -coord.t = float (clamp (float(coord.t), dtH, 1.0 - dtH)); -coord.r = float (clamp (float(coord.r), 0.0, 1.0)); +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; -myhalf shadow0 = myhalf(shadow2D(ShadowmapTexture, coord).r); -myhalf shadow = shadow0; +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors -#if defined(APPLY_PCF2x2) || defined(APPLY_PCF3x3) +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; -vec3 coord2 = coord + vec3(0.0, dtH, 0.0); -myhalf shadow1 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +uniform myhalf2 u_BlendMix; -coord2 = coord + vec3(dtW, dtH, 0.0); -myhalf shadow2 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) -coord2 = coord + vec3(dtW, 0.0, 0.0); -myhalf shadow3 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +uniform float u_MirrorSide; -#if defined(APPLY_PCF3x3) -coord2 = coord + vec3(-dtW, 0.0, 0.0); -myhalf shadow4 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +uniform float u_ZNear, u_ZFar; -coord2 = coord + vec3(-dtW, -dtH, 0.0); -myhalf shadow5 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +uniform ivec4 u_Viewport; // x, y, width, height -coord2 = coord + vec3(0.0, -dtH, 0.0); -myhalf shadow6 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +uniform vec4 u_TextureParams; -coord2 = coord + vec3(dtW, -dtH, 0.0); -myhalf shadow7 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +uniform myhalf u_SoftParticlesScale; -coord2 = coord + vec3(-dtW, dtH, 0.0); -myhalf shadow8 = myhalf (shadow2D (ShadowmapTexture, coord2).r); -shadow = (shadow0 + shadow1 + shadow2 + shadow3 + shadow4 + shadow5 + shadow6 + shadow7 + shadow8) * myhalf(0.11); +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) #else -shadow = (shadow0 + shadow1 + shadow2 + shadow3) * myhalf(0.25); +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) #else -shadow = shadow0; + for (int i = 0; i < NUM_DLIGHTS; i++) #endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); -float attenuation = float (ProjVector.w) / ProjDistance; -myhalf compensation = myhalf(0.25) - max(LightAmbient.x, max(LightAmbient.y, LightAmbient.z)) -;compensation = max (compensation, 0.0); -color = shadow + attenuation + compensation; + falloff *= falloff; -gl_FragColor = vec4(vec3(color),1.0); -} + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif -#endif // FRAGMENT_SHADER + Color += falloff * u_DynamicLights[i].Diffuse; + } + return Color; +} -[vertex shader] -#define VERTEX_SHADER -// Warsow GLSL shader -#if !defined(__GLSL_CG_DATA_TYPES) -#define myhalf float -#define myhalf2 vec2 -#define myhalf3 vec3 -#define myhalf4 vec4 +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif #endif -varying vec4 ProjVector; +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif #ifdef VERTEX_SHADER -// Vertex shader +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -void main(void) +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) { -gl_FrontColor = gl_Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif +#endif -mat4 textureMatrix; +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif -textureMatrix = gl_TextureMatrix[0]; +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif -gl_Position = ftransform(); -ProjVector = textureMatrix * gl_Vertex; + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif } -#endif // VERTEX_SHADER +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER #ifdef FRAGMENT_SHADER // Fragment shader -uniform myhalf3 LightAmbient; +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor -uniform float TextureWidth, TextureHeight; -uniform float ProjDistance; -uniform sampler2DShadow ShadowmapTexture; +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -void main(void) +void main() { -myhalf color = myhalf(1.0); +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); -if (ProjVector.w <= 0.0 || ProjVector.w >= ProjDistance) -discard; + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); -float dtW = 1.0 / TextureWidth; -float dtH = 1.0 / TextureHeight; + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT -vec3 coord = vec3 (ProjVector.xyz / ProjVector.w); -coord = (coord + vec3 (1.0)) * vec3 (0.5); -coord.s = float (clamp (float(coord.s), dtW, 1.0 - dtW)); -coord.t = float (clamp (float(coord.t), dtH, 1.0 - dtH)); -coord.r = float (clamp (float(coord.r), 0.0, 1.0)); +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif -myhalf shadow0 = myhalf(shadow2D(ShadowmapTexture, coord).r); -myhalf shadow = shadow0; +#endif // APPLY_CELSHADING -#if defined(APPLY_PCF2x2) || defined(APPLY_PCF3x3) +#endif // APPLY_DIRECTIONAL_LIGHT -vec3 coord2 = coord + vec3(0.0, dtH, 0.0); -myhalf shadow1 = myhalf (shadow2D (ShadowmapTexture, coord2).r); + // deluxemapping using light vectors in modelspace -coord2 = coord + vec3(dtW, dtH, 0.0); -myhalf shadow2 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); -coord2 = coord + vec3(dtW, 0.0, 0.0); -myhalf shadow3 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif -#if defined(APPLY_PCF3x3) -coord2 = coord + vec3(-dtW, 0.0, 0.0); -myhalf shadow4 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif -coord2 = coord + vec3(-dtW, -dtH, 0.0); -myhalf shadow5 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +#ifdef APPLY_SPECULAR -coord2 = coord + vec3(0.0, -dtH, 0.0); -myhalf shadow6 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif -coord2 = coord + vec3(dtW, -dtH, 0.0); -myhalf shadow7 = myhalf (shadow2D (ShadowmapTexture, coord2).r); + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR -coord2 = coord + vec3(-dtW, dtH, 0.0); -myhalf shadow8 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; -shadow = (shadow0 + shadow1 + shadow2 + shadow3 + shadow4 + shadow5 + shadow6 + shadow7 + shadow8) * myhalf(0.11); +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); #else -shadow = (shadow0 + shadow1 + shadow2 + shadow3) * myhalf(0.25); + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); #endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; #else -shadow = shadow0; + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); #endif -float attenuation = float (ProjVector.w) / ProjDistance; -myhalf compensation = myhalf(0.25) - max(LightAmbient.x, max(LightAmbient.y, LightAmbient.z)) -;compensation = max (compensation, 0.0); -color = shadow + attenuation + compensation; +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif -gl_FragColor = vec4(vec3(color),1.0); + qf_FragColor = vec4(color); } #endif // FRAGMENT_SHADER - diff --git a/shaders/warsow/52.shader_test b/shaders/warsow/52.shader_test index b4f6f7c..5504683 100644 --- a/shaders/warsow/52.shader_test +++ b/shaders/warsow/52.shader_test @@ -1,103 +1,2059 @@ [require] GLSL >= 1.10 +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_SPECULAR +#define APPLY_DIRECTIONAL_LIGHT_MIX + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + [fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 #define FRAGMENT_SHADER -// Warsow GLSL shader +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; +vec4 DQReal1, DQDual1; +float scale; -varying vec4 ProjVector; +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif #ifdef VERTEX_SHADER -// Vertex shader +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_SPECULAR +#define APPLY_DIRECTIONAL_LIGHT_MIX + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) -uniform float OutlineHeight; +uniform float u_MirrorSide; -void main(void) +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif { -gl_FrontColor = gl_Color; + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} -vec4 n = vec4(gl_Normal.xyz, 0.0); -vec4 v = vec4(gl_Vertex) + n * OutlineHeight; -gl_Position = gl_ModelViewProjectionMatrix * v; -ProjVector = gl_Position; -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * v; +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) #endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; } -#endif // VERTEX_SHADER +#endif + +#endif +#endif -#ifdef FRAGMENT_SHADER -// Fragment shader +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 -uniform float OutlineCutOff; +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) -void main(void) +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif { + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); -#ifdef APPLY_OUTLINES_CUTOFF -if (OutlineCutOff > 0.0 && (ProjVector.w > OutlineCutOff)) -discard; +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -gl_FragColor = vec4 (gl_Color); +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif } -#endif // FRAGMENT_SHADER +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); -[vertex shader] -#define VERTEX_SHADER -// Warsow GLSL shader +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) -varying vec4 ProjVector; +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif #ifdef VERTEX_SHADER -// Vertex shader +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} -uniform float OutlineHeight; +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif -void main(void) +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() { -gl_FrontColor = gl_Color; + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; -vec4 n = vec4(gl_Normal.xyz, 0.0); -vec4 v = vec4(gl_Vertex) + n * OutlineHeight; + TransformVerts(Position, Normal, Tangent, TexCoord); -gl_Position = gl_ModelViewProjectionMatrix * v; -ProjVector = gl_Position; -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * v; + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); #endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; #endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; } #endif // VERTEX_SHADER - #ifdef FRAGMENT_SHADER // Fragment shader -uniform float OutlineCutOff; +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -void main(void) +void main() { +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT -#ifdef APPLY_OUTLINES_CUTOFF -if (OutlineCutOff > 0.0 && (ProjVector.w > OutlineCutOff)) -discard; +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; #endif -gl_FragColor = vec4 (gl_Color); +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); } #endif // FRAGMENT_SHADER - diff --git a/shaders/warsow/55.shader_test b/shaders/warsow/55.shader_test index 3e97234..19edae8 100644 --- a/shaders/warsow/55.shader_test +++ b/shaders/warsow/55.shader_test @@ -1,140 +1,1281 @@ [require] GLSL >= 1.10 -[fragment shader] -#define FRAGMENT_SHADER -// Warsow GLSL shader - -#if !defined(__GLSL_CG_DATA_TYPES) +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI #define M_TWOPI 6.28318530717958647692 +#endif -varying vec2 TexCoord; +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform float TurbAmplitude, TurbPhase; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -void main(void) +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -vec4 turb; -turb = vec4(gl_MultiTexCoord0); -turb.s += TurbAmplitude * sin( ((gl_MultiTexCoord0.t / 4.0 + TurbPhase)) * M_TWOPI ); -turb.t += TurbAmplitude * sin( ((gl_MultiTexCoord0.s / 4.0 + TurbPhase)) * M_TWOPI ); -TexCoord = vec2(gl_TextureMatrix[0] * turb); +vec4 DQReal1, DQDual1; +float scale; -gl_Position = ftransform(); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif } -#endif // VERTEX_SHADER +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_DUDV +#define APPLY_DISTORTION_ALPHA +#define APPLY_REFRACTION + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + + +qf_varying vec4 v_TexCoord; +qf_varying vec4 v_ProjVector; +#ifdef APPLY_EYEDOT +qf_varying vec3 v_EyeVector; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#ifdef APPLY_EYEDOT +uniform float u_FrontPlane; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + qf_FrontColor = vec4(VertexRGBGen(Position, Normal, inColor)); + + v_TexCoord.st = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + + vec2 textureMatrix3_[3]; + textureMatrix3_[0] = u_TextureMatrix[0]; + textureMatrix3_[1] = u_TextureMatrix[1]; + textureMatrix3_[2] = -u_TextureMatrix[2]; + v_TexCoord.pq = TextureMatrix2x3Mul(textureMatrix3_, TexCoord); + +#ifdef APPLY_EYEDOT + mat3 v_StrMatrix; + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + + vec3 EyeVectorWorld = (u_ViewOrigin - Position.xyz) * u_FrontPlane; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + gl_Position = u_ModelViewProjectionMatrix * Position; + v_ProjVector = gl_Position; +} + +#endif // VERTEX_SHADER #ifdef FRAGMENT_SHADER // Fragment shader -uniform sampler2D BaseTexture; +#ifdef APPLY_DUDV +uniform sampler2D u_DuDvMapTexture; +#endif + +#ifdef APPLY_EYEDOT +uniform sampler2D u_NormalmapTexture; +#endif +uniform sampler2D u_ReflectionTexture; +uniform sampler2D u_RefractionTexture; void main(void) { + myhalf3 color; -myhalf4 color; +#ifdef APPLY_DUDV + vec3 displacement = vec3(qf_texture(u_DuDvMapTexture, vec2(v_TexCoord.pq) * vec2(0.25))); + vec2 coord = vec2(v_TexCoord.st) + vec2(displacement) * vec2 (0.2); -color = myhalf4(gl_Color) * myhalf4(texture2D(BaseTexture, TexCoord)); + vec3 fdist = vec3 (normalize(vec3(qf_texture(u_DuDvMapTexture, coord)) - vec3 (0.5))) * vec3(0.005); +#else + vec3 fdist = vec3(0.0); +#endif -gl_FragColor = vec4(color); -} + // get projective texcoords + float scale = float(1.0 / float(v_ProjVector.w)); + float inv2NW = u_TextureParams.z * 0.5; // .z - inverse width + float inv2NH = u_TextureParams.w * 0.5; // .w - inverse height + vec2 projCoord = (vec2(v_ProjVector.xy) * scale + vec2 (1.0)) * vec2 (0.5) + vec2(fdist.xy); + projCoord.s = float (clamp (float(projCoord.s), inv2NW, 1.0 - inv2NW)); + projCoord.t = float (clamp (float(projCoord.t), inv2NH, 1.0 - inv2NH)); -#endif // FRAGMENT_SHADER + myhalf3 refr = myhalf3(0.0); + myhalf3 refl = myhalf3(0.0); +#ifdef APPLY_EYEDOT + // calculate dot product between the surface normal and eye vector + // great for simulating qf_varying water translucency based on the view angle + myhalf3 surfaceNormal = normalize(myhalf3(qf_texture(u_NormalmapTexture, coord)) - myhalf3 (0.5)); + vec3 eyeNormal = normalize(myhalf3(v_EyeVector)); - -===================================== -wdm16 - -Silver connected from 127.0.0.1 -Silver skill 50 -Sector connected from 127.0.0.1 -Sector skill 50 + float refrdot = float(dot(surfaceNormal, eyeNormal)); + //refrdot = float (clamp (refrdot, 0.0, 1.0)); + float refldot = 1.0 - refrdot; + // get refraction and reflection -[vertex shader] -#define VERTEX_SHADER -// Warsow GLSL shader +#ifdef APPLY_REFRACTION + refr = (myhalf3(qf_texture(u_RefractionTexture, projCoord))) * refrdot; +#endif +#ifdef APPLY_REFLECTION + refl = (myhalf3(qf_texture(u_ReflectionTexture, projCoord))) * refldot; +#endif + +#else + +#ifdef APPLY_REFRACTION + refr = (myhalf3(qf_texture(u_RefractionTexture, projCoord))); +#endif +#ifdef APPLY_REFLECTION + refl = (myhalf3(qf_texture(u_ReflectionTexture, projCoord))); +#endif + +#endif // APPLY_EYEDOT + + // add reflection and refraction +#ifdef APPLY_DISTORTION_ALPHA + color = myhalf3(qf_FrontColor.rgb) + myhalf3(mix (refr, refl, myhalf(qf_FrontColor.a))); +#else + color = myhalf3(qf_FrontColor.rgb) + refr + refl; +#endif + +#ifdef APPLY_GREYSCALE + qf_FragColor = vec4(vec3(Greyscale(color)),1.0); +#else + qf_FragColor = vec4(vec3(color),1.0); +#endif +} -#if !defined(__GLSL_CG_DATA_TYPES) +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI #define M_TWOPI 6.28318530717958647692 +#endif -varying vec2 TexCoord; +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform float TurbAmplitude, TurbPhase; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -void main(void) +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -vec4 turb; -turb = vec4(gl_MultiTexCoord0); -turb.s += TurbAmplitude * sin( ((gl_MultiTexCoord0.t / 4.0 + TurbPhase)) * M_TWOPI ); -turb.t += TurbAmplitude * sin( ((gl_MultiTexCoord0.s / 4.0 + TurbPhase)) * M_TWOPI ); -TexCoord = vec2(gl_TextureMatrix[0] * turb); +vec4 DQReal1, DQDual1; +float scale; -gl_Position = ftransform(); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif } -#endif // VERTEX_SHADER +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_DUDV +#define APPLY_DISTORTION_ALPHA +#define APPLY_REFRACTION + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + + +qf_varying vec4 v_TexCoord; +qf_varying vec4 v_ProjVector; +#ifdef APPLY_EYEDOT +qf_varying vec3 v_EyeVector; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#ifdef APPLY_EYEDOT +uniform float u_FrontPlane; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + qf_FrontColor = vec4(VertexRGBGen(Position, Normal, inColor)); + + v_TexCoord.st = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + + vec2 textureMatrix3_[3]; + textureMatrix3_[0] = u_TextureMatrix[0]; + textureMatrix3_[1] = u_TextureMatrix[1]; + textureMatrix3_[2] = -u_TextureMatrix[2]; + v_TexCoord.pq = TextureMatrix2x3Mul(textureMatrix3_, TexCoord); + +#ifdef APPLY_EYEDOT + mat3 v_StrMatrix; + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + + vec3 EyeVectorWorld = (u_ViewOrigin - Position.xyz) * u_FrontPlane; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + gl_Position = u_ModelViewProjectionMatrix * Position; + v_ProjVector = gl_Position; +} + +#endif // VERTEX_SHADER #ifdef FRAGMENT_SHADER // Fragment shader -uniform sampler2D BaseTexture; +#ifdef APPLY_DUDV +uniform sampler2D u_DuDvMapTexture; +#endif + +#ifdef APPLY_EYEDOT +uniform sampler2D u_NormalmapTexture; +#endif +uniform sampler2D u_ReflectionTexture; +uniform sampler2D u_RefractionTexture; void main(void) { + myhalf3 color; + +#ifdef APPLY_DUDV + vec3 displacement = vec3(qf_texture(u_DuDvMapTexture, vec2(v_TexCoord.pq) * vec2(0.25))); + vec2 coord = vec2(v_TexCoord.st) + vec2(displacement) * vec2 (0.2); + + vec3 fdist = vec3 (normalize(vec3(qf_texture(u_DuDvMapTexture, coord)) - vec3 (0.5))) * vec3(0.005); +#else + vec3 fdist = vec3(0.0); +#endif + + // get projective texcoords + float scale = float(1.0 / float(v_ProjVector.w)); + float inv2NW = u_TextureParams.z * 0.5; // .z - inverse width + float inv2NH = u_TextureParams.w * 0.5; // .w - inverse height + vec2 projCoord = (vec2(v_ProjVector.xy) * scale + vec2 (1.0)) * vec2 (0.5) + vec2(fdist.xy); + projCoord.s = float (clamp (float(projCoord.s), inv2NW, 1.0 - inv2NW)); + projCoord.t = float (clamp (float(projCoord.t), inv2NH, 1.0 - inv2NH)); + + myhalf3 refr = myhalf3(0.0); + myhalf3 refl = myhalf3(0.0); + +#ifdef APPLY_EYEDOT + // calculate dot product between the surface normal and eye vector + // great for simulating qf_varying water translucency based on the view angle + myhalf3 surfaceNormal = normalize(myhalf3(qf_texture(u_NormalmapTexture, coord)) - myhalf3 (0.5)); + vec3 eyeNormal = normalize(myhalf3(v_EyeVector)); + + float refrdot = float(dot(surfaceNormal, eyeNormal)); + //refrdot = float (clamp (refrdot, 0.0, 1.0)); + float refldot = 1.0 - refrdot; + // get refraction and reflection -myhalf4 color; +#ifdef APPLY_REFRACTION + refr = (myhalf3(qf_texture(u_RefractionTexture, projCoord))) * refrdot; +#endif +#ifdef APPLY_REFLECTION + refl = (myhalf3(qf_texture(u_ReflectionTexture, projCoord))) * refldot; +#endif + +#else + +#ifdef APPLY_REFRACTION + refr = (myhalf3(qf_texture(u_RefractionTexture, projCoord))); +#endif +#ifdef APPLY_REFLECTION + refl = (myhalf3(qf_texture(u_ReflectionTexture, projCoord))); +#endif -color = myhalf4(gl_Color) * myhalf4(texture2D(BaseTexture, TexCoord)); +#endif // APPLY_EYEDOT -gl_FragColor = vec4(color); + // add reflection and refraction +#ifdef APPLY_DISTORTION_ALPHA + color = myhalf3(qf_FrontColor.rgb) + myhalf3(mix (refr, refl, myhalf(qf_FrontColor.a))); +#else + color = myhalf3(qf_FrontColor.rgb) + refr + refl; +#endif + +#ifdef APPLY_GREYSCALE + qf_FragColor = vec4(vec3(Greyscale(color)),1.0); +#else + qf_FragColor = vec4(vec3(color),1.0); +#endif } #endif // FRAGMENT_SHADER - diff --git a/shaders/warsow/58.shader_test b/shaders/warsow/58.shader_test new file mode 100644 index 0000000..ee0f427 --- /dev/null +++ b/shaders/warsow/58.shader_test @@ -0,0 +1,1751 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif + +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec3 v_Position; + +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif + +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif + +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; +#else +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; +#endif + +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; + + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); +#else + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) +{ + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; +} + +#endif + + +uniform sampler2D u_DepthTexture; + +#endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#else + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); +#endif + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/60.shader_test b/shaders/warsow/60.shader_test deleted file mode 100644 index 30ba541..0000000 --- a/shaders/warsow/60.shader_test +++ /dev/null @@ -1,17 +0,0 @@ -[require] -GLSL >= 1.10 - -[fragment shader] -uniform vec4 color; -void main() -{ - gl_FragColor = color; -} - -[vertex shader] -attribute vec4 position; -void main() -{ - gl_Position = position; -} - diff --git a/shaders/warsow/61.shader_test b/shaders/warsow/61.shader_test new file mode 100644 index 0000000..62f4076 --- /dev/null +++ b/shaders/warsow/61.shader_test @@ -0,0 +1,2057 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_DIRECTIONAL_LIGHT_MIX + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_DIRECTIONAL_LIGHT_MIX + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/63.shader_test b/shaders/warsow/63.shader_test deleted file mode 100644 index 7497b6b..0000000 --- a/shaders/warsow/63.shader_test +++ /dev/null @@ -1,22 +0,0 @@ -[require] -GLSL >= 1.10 - -[fragment shader] -#version 130 -uniform ivec4 color; -out ivec4 out_color; - -void main() -{ - out_color = color; -} - -[vertex shader] -#version 130 -in vec4 position; -void main() -{ - gl_Position = position; -} - - diff --git a/shaders/warsow/64.shader_test b/shaders/warsow/64.shader_test index b59d973..8033677 100644 --- a/shaders/warsow/64.shader_test +++ b/shaders/warsow/64.shader_test @@ -1,696 +1,1755 @@ [require] GLSL >= 1.10 -[fragment shader] -#define FRAGMENT_SHADER -#define APPLY_LIGHTSTYLE0 -#define APPLY_FBLIGHTMAP -#define APPLY_AMBIENT_COMPENSATION -// Warsow GLSL shader - -#if !defined(__GLSL_CG_DATA_TYPES) +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 #endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -void main() +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color - -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + #endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_RGB_DISTANCERAMP +#define APPLY_ALPHA_CONST +#define APPLY_SOFT_PARTICLE + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) #endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) #else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; + for (int i = 0; i < NUM_DLIGHTS; i++) #endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; } + + +#endif + +#endif #endif -void main() +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif { -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif +} -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); -#else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif +} -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +#endif -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#endif -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +qf_varying vec3 v_Position; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; #else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; #endif +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; #endif -// deluxemapping using light vectors in modelspace +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif -#ifdef APPLY_LIGHTSTYLE0 +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} -#define NORMALIZE_DIFFUSE_NORMAL +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) #endif -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +#endif +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); #endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); #endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP #endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; #endif -#ifdef APPLY_SPECULAR +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); #else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); + FogGen(Position, v_FogCoord); #endif +#endif // APPLY_FOG -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); -#endif + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); #else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; #endif -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; } + +#endif + + +uniform sampler2D u_DepthTexture; + #endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 #else -color = color * myhalf4(gl_Color.rgba); + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); #else -gl_FragColor = vec4(color); + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); #endif -} -#endif // FRAGMENT_SHADER +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + color *= diffuse; +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif -[vertex shader] -#define VERTEX_SHADER -#define APPLY_LIGHTSTYLE0 -#define APPLY_FBLIGHTMAP -#define APPLY_AMBIENT_COMPENSATION -// Warsow GLSL shader +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); +} -#if !defined(__GLSL_CG_DATA_TYPES) +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 #endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -void main() +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color - -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + #endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_RGB_DISTANCERAMP +#define APPLY_ALPHA_CONST +#define APPLY_SOFT_PARTICLE + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) #endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) #else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; + for (int i = 0; i < NUM_DLIGHTS; i++) #endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; } + + +#endif + +#endif #endif -void main() +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif { -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif +} -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); -#else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif +} -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +#endif -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#endif -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +qf_varying vec3 v_Position; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +#ifdef APPLY_DRAWFLAT +qf_varying myhalf v_NormalZ; +#endif -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +#ifdef APPLY_TC_GEN_REFLECTION +#define APPLY_CUBEMAP +#endif -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#ifdef APPLY_CUBEMAP +qf_varying vec3 v_TexCoord; #else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; +qf_varying vec2 v_TexCoord; +#endif + +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; #endif +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; #endif -// deluxemapping using light vectors in modelspace +#if defined(APPLY_SOFT_PARTICLE) +qf_varying float v_Depth; +#endif -#ifdef APPLY_LIGHTSTYLE0 +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} -#define NORMALIZE_DIFFUSE_NORMAL +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) #endif -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +#endif +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); #endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); #endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP #endif +} + + +#if defined(APPLY_TC_GEN_REFLECTION) +uniform mat4 u_ReflectionTexMatrix; +#elif defined(APPLY_TC_GEN_VECTOR) +uniform mat4 u_VectorTexMatrix; #endif -#ifdef APPLY_SPECULAR +void main(void) +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); #else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); + FogGen(Position, v_FogCoord); #endif +#endif // APPLY_FOG -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); -#endif + qf_FrontColor = vec4(outColor); + +#if defined(APPLY_TC_GEN_ENV) + vec3 Projection; -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); + Projection = u_EntityDist - Position.xyz; + Projection = normalize(Projection); + + float Depth = dot(Normal.xyz, Projection) * 2.0; + v_TexCoord = vec2(0.5 + (Normal.y * Depth - Projection.y) * 0.5, 0.5 - (Normal.z * Depth - Projection.z) * 0.5); +#elif defined(APPLY_TC_GEN_VECTOR) + v_TexCoord = vec2(u_VectorTexMatrix * Position); +#elif defined(APPLY_TC_GEN_REFLECTION) + v_TexCoord = vec3(u_ReflectionTexMatrix * vec4(reflect(normalize(Position.xyz - u_EntityDist), Normal.xyz), 0.0)); +#elif defined(APPLY_TC_GEN_PROJECTION) + v_TexCoord = vec2(normalize(u_ModelViewProjectionMatrix * Position) * 0.5 + vec4(0.5)); #else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); +#endif // defined(APPLY_TC_GEN_ENV) + + v_Position = Position.xyz; + +#ifdef APPLY_DRAWFLAT + v_NormalZ = Normal.z; +#endif + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + gl_Position = u_ModelViewProjectionMatrix * Position; + +#if defined(APPLY_SOFT_PARTICLE) + vec4 modelPos = u_ModelViewMatrix * Position; + v_Depth = -modelPos.z; +#endif +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef APPLY_CUBEMAP +uniform samplerCube u_BaseTexture; +#else +uniform sampler2D u_BaseTexture; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + +#ifdef NUM_LIGHTMAPS +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; #endif -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) +#if defined(APPLY_SOFT_PARTICLE) +#ifdef FRAGMENT_SHADER + +myhalf FragmentSoftness(float Depth, sampler2D DepthTexture, in vec2 ScreenCoord, in ivec4 Viewport, in float ZNear, in float ZFar, myhalf Scale) { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); + vec2 tc = ScreenCoord * u_TextureParams.zw; + + myhalf fragdepth = ZNear*ZFar/(ZFar - qf_texture(DepthTexture, tc).r*(ZFar-ZNear)); + myhalf partdepth = Depth; + + myhalf d = max((fragdepth - partdepth) * Scale, 0.0); + myhalf softness = 1.0 - min(1.0, d); + + softness *= softness; + softness = 1.0 - softness * softness; + return softness; } + +#endif + + +uniform sampler2D u_DepthTexture; + #endif + +void main(void) +{ + myhalf4 color; + +#ifdef NUM_LIGHTMAPS + color = myhalf4(0.0, 0.0, 0.0, qf_FrontColor.a); + color.rgb += myhalf3(qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])) * u_LightstyleColor[0]; +#if NUM_LIGHTMAPS >= 2 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])) * u_LightstyleColor[1]; +#if NUM_LIGHTMAPS >= 3 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])) * u_LightstyleColor[2]; +#if NUM_LIGHTMAPS >= 4 + color.rgb += myhalf3(qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])) * u_LightstyleColor[3]; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 #else -color = color * myhalf4(gl_Color.rgba); + color = myhalf4(qf_FrontColor); +#endif // NUM_LIGHTMAPS + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position); +#endif + + myhalf4 diffuse; + +#ifdef APPLY_CUBEMAP + diffuse = myhalf4(qf_textureCube(u_BaseTexture, v_TexCoord)); #else -gl_FragColor = vec4(color); + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); #endif + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_NormalZ))); + diffuse.rgb = myhalf3(mix(u_WallColor, u_FloorColor, n)); +#endif + + color *= diffuse; + +#ifdef NUM_LIGHTMAPS + // so that team-colored shaders work + color *= myhalf4(qf_FrontColor); +#endif + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + +#if defined(APPLY_SOFT_PARTICLE) + myhalf softness = FragmentSoftness(v_Depth, u_DepthTexture, gl_FragCoord.xy, u_Viewport, u_ZNear, u_ZFar, u_SoftParticlesScale); + color *= mix(myhalf4(1.0), myhalf4(softness), u_BlendMix.xxxy); +#endif + + qf_FragColor = vec4(color); } #endif // FRAGMENT_SHADER - diff --git a/shaders/warsow/67.shader_test b/shaders/warsow/67.shader_test index f005219..4d04939 100644 --- a/shaders/warsow/67.shader_test +++ b/shaders/warsow/67.shader_test @@ -1,481 +1,1801 @@ [require] GLSL >= 1.10 +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 3 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_HALFLAMBERT +#define APPLY_ENTITY_DECAL + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + [fragment shader] -#define FRAGMENT_SHADER -// Warsow GLSL shader +#version 130 -#if !defined(__GLSL_CG_DATA_TYPES) +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -void main() +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; -#endif -#endif -#endif -#endif +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; -#endif +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; -#endif +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; -#endif +vec4 DQReal1, DQDual1; +float scale; -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +if (numWeights > 2) { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} } +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -void main() -{ -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#define NUM_BONE_INFLUENCES 3 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_HALFLAMBERT +#define APPLY_ENTITY_DECAL -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +uniform float u_ShaderTime; -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); -#else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; -#endif +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; -#endif +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors -// deluxemapping using light vectors in modelspace +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; -#ifdef APPLY_LIGHTSTYLE0 +uniform myhalf2 u_BlendMix; -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +uniform float u_MirrorSide; -#define NORMALIZE_DIFFUSE_NORMAL +uniform float u_ZNear, u_ZFar; -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); -#endif +uniform ivec4 u_Viewport; // x, y, width, height -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; -#endif +uniform vec4 u_TextureParams; -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); +uniform myhalf u_SoftParticlesScale; -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) #endif -#endif -#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); -#ifdef APPLY_SPECULAR + falloff *= falloff; -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) #else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); #endif -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); -#else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); #endif -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) +#ifdef APPLY_FOG +struct Fog { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); -} + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) #endif -#else -color = color * myhalf4(gl_Color.rgba); +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); -#else -gl_FragColor = vec4(color); +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif } -#endif // FRAGMENT_SHADER +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); -[vertex shader] -#define VERTEX_SHADER -// Warsow GLSL shader +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} -#if !defined(__GLSL_CG_DATA_TYPES) -#define myhalf float -#define myhalf2 vec2 -#define myhalf3 vec3 -#define myhalf4 vec4 -#else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 #endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; #endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; #endif +qf_varying vec3 v_Position; + #if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +qf_varying vec3 v_EyeVector; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; -#endif +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif #ifdef VERTEX_SHADER -// Vertex shader +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif -uniform vec3 EyeOrigin; +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} -void main() +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) { -gl_FrontColor = gl_Color; - -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) #endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); #endif -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); #endif -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); #endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP #endif } -#endif // VERTEX_SHADER +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); -#ifdef FRAGMENT_SHADER -// Fragment shader + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; + qf_FrontColor = vec4(outColor); -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; #endif -#endif -#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; #endif -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; #ifdef APPLY_DECAL -uniform sampler2D DecalTexture; +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; #endif #if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; +uniform float u_OffsetMappingScale; #endif -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; #endif -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor #if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) // The following reliefmapping and offsetmapping routine was taken from DarkPlaces @@ -483,207 +1803,259 @@ uniform myhalf GlossExponent; // gloss exponent factor vec2 OffsetMapping(vec2 TexCoord) { #ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING } -#endif +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) void main() { #if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; #endif -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; + myhalf3 weightedDiffuseNormalModelspace; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); #ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); #else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; -#endif +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; #endif -// deluxemapping using light vectors in modelspace +#endif // APPLY_CELSHADING -#ifdef APPLY_LIGHTSTYLE0 +#endif // APPLY_DIRECTIONAL_LIGHT -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); #ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); #else - #define NORMALIZE_DIFFUSE_NORMAL - -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); -#endif + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP #ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; -#endif - -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); - -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); - -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); - -#endif -#endif -#endif + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); #endif #ifdef APPLY_SPECULAR #ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); #else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); #endif -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); -#endif + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); #else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); -#endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); #endif +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + #ifdef APPLY_DECAL + #ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); #else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) -{ -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); -} -#endif + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + #else -color = color * myhalf4(gl_Color.rgba); -#endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; #else -gl_FragColor = vec4(color); + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); #endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); } #endif // FRAGMENT_SHADER - diff --git a/shaders/warsow/7.shader_test b/shaders/warsow/7.shader_test index 6e68fc9..b100519 100644 --- a/shaders/warsow/7.shader_test +++ b/shaders/warsow/7.shader_test @@ -1,695 +1,979 @@ [require] GLSL >= 1.10 -[fragment shader] -#define FRAGMENT_SHADER -#define APPLY_LIGHTSTYLE0 -#define APPLY_FBLIGHTMAP -#define APPLY_SPECULAR -// Warsow GLSL shader - -#if !defined(__GLSL_CG_DATA_TYPES) +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 #endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -void main() +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; -#endif -#endif -#endif -#endif +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; -#endif +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; -#endif +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; -#endif +vec4 DQReal1, DQDual1; +float scale; -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +if (numWeights > 2) { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} } +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -void main() -{ -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +uniform float u_ShaderTime; -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); -#else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; -#endif +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; -#endif +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors -// deluxemapping using light vectors in modelspace +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; -#ifdef APPLY_LIGHTSTYLE0 +uniform myhalf2 u_BlendMix; -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +uniform float u_MirrorSide; -#define NORMALIZE_DIFFUSE_NORMAL +uniform float u_ZNear, u_ZFar; -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); -#endif +uniform ivec4 u_Viewport; // x, y, width, height -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; -#endif +uniform vec4 u_TextureParams; -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) +#endif -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +qf_varying float v_Depth; -#endif -#endif -#endif +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); #endif -#ifdef APPLY_SPECULAR +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); -#else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); #endif -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); -#else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) + +void main(void) { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + v_Depth = gl_Position.z; } -#endif -#else -color = color * myhalf4(gl_Color.rgba); -#endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); -#else -gl_FragColor = vec4(color); -#endif +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +void main(void) +{ + qf_FragColor = encodedepthmacro(v_Depth); } #endif // FRAGMENT_SHADER +[fragment shader] +#version 130 -[vertex shader] -#define VERTEX_SHADER -#define APPLY_LIGHTSTYLE0 -#define APPLY_FBLIGHTMAP -#define APPLY_SPECULAR -// Warsow GLSL shader - -#if !defined(__GLSL_CG_DATA_TYPES) +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 #endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -void main() +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; -#endif -#endif -#endif -#endif +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; -#endif +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; -#endif +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; -#endif +vec4 DQReal1, DQDual1; +float scale; -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +if (numWeights > 2) { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} } +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -void main() -{ -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +uniform float u_ShaderTime; -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); -#else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; -#endif +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; -#endif +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors -// deluxemapping using light vectors in modelspace +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; -#ifdef APPLY_LIGHTSTYLE0 +uniform myhalf2 u_BlendMix; -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +uniform float u_MirrorSide; -#define NORMALIZE_DIFFUSE_NORMAL +uniform float u_ZNear, u_ZFar; -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); -#endif +uniform ivec4 u_Viewport; // x, y, width, height -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; -#endif +uniform vec4 u_TextureParams; -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); +uniform myhalf u_SoftParticlesScale; +#ifndef decodedepthmacro +// Lifted from Darkplaces shader program +#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0)) +#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0))) +#endif -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +qf_varying float v_Depth; -#endif -#endif -#endif +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); #endif -#ifdef APPLY_SPECULAR +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); -#else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); #endif -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); -#else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) + +void main(void) { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + + TransformVerts(Position, Normal, TexCoord); + + gl_Position = u_ModelViewProjectionMatrix * Position; + v_Depth = gl_Position.z; } -#endif -#else -color = color * myhalf4(gl_Color.rgba); -#endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); -#else -gl_FragColor = vec4(color); -#endif +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +void main(void) +{ + qf_FragColor = encodedepthmacro(v_Depth); } #endif // FRAGMENT_SHADER - diff --git a/shaders/warsow/70.shader_test b/shaders/warsow/70.shader_test index 62d5d00..96f5d3c 100644 --- a/shaders/warsow/70.shader_test +++ b/shaders/warsow/70.shader_test @@ -1,691 +1,1239 @@ [require] GLSL >= 1.10 -[fragment shader] -#define FRAGMENT_SHADER -#define APPLY_LIGHTSTYLE0 -#define APPLY_FBLIGHTMAP -// Warsow GLSL shader - -#if !defined(__GLSL_CG_DATA_TYPES) +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 #endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -void main() +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; -#endif -#endif -#endif -#endif +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; -#endif +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; -#endif +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; -#endif +vec4 DQReal1, DQDual1; +float scale; -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +if (numWeights > 2) { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} } + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -void main() -{ -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#define NUM_BONE_INFLUENCES 3 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +uniform float u_ShaderTime; -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); -#else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) #endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -// deluxemapping using light vectors in modelspace +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} -#ifdef APPLY_LIGHTSTYLE0 -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif -#define NORMALIZE_DIFFUSE_NORMAL +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); #endif -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); #endif -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) #endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); #endif -#ifdef APPLY_SPECULAR +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); -#else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); #endif -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); #endif -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); -#else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP #endif +} -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) + +uniform float u_OutlineHeight; + +void main(void) { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); -} -#endif -#else -color = color * myhalf4(gl_Color.rgba); + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + Position += vec4(Normal * u_OutlineHeight, 0.0); + gl_Position = u_ModelViewProjectionMatrix * Position; + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG + myhalf4 tempColor = myhalf4(1.0); + FogGen(Position, tempColor, myhalf2(0.0, 1.0)); + outColor.rgb = mix(u_Fog.Color, outColor.rgb, tempColor.a); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); -#else -gl_FragColor = vec4(color); + qf_FrontColor = vec4(outColor); +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform float u_OutlineCutOff; + +void main(void) +{ +#ifdef APPLY_OUTLINES_CUTOFF + if (u_OutlineCutOff > 0.0 && (gl_FragCoord.z / gl_FragCoord.w > u_OutlineCutOff)) + discard; #endif + qf_FragColor = vec4(qf_FrontColor); } #endif // FRAGMENT_SHADER -[vertex shader] -#define VERTEX_SHADER -#define APPLY_LIGHTSTYLE0 -#define APPLY_FBLIGHTMAP -// Warsow GLSL shader +[fragment shader] +#version 130 -#if !defined(__GLSL_CG_DATA_TYPES) +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 #endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -void main() +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; -#endif -#endif -#endif -#endif +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; -#endif +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; -#endif +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; -#endif +vec4 DQReal1, DQDual1; +float scale; -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +if (numWeights > 2) { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} } +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -void main() -{ -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#define NUM_BONE_INFLUENCES 3 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +uniform float u_ShaderTime; -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); -#else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) #endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -// deluxemapping using light vectors in modelspace +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} -#ifdef APPLY_LIGHTSTYLE0 -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif -#define NORMALIZE_DIFFUSE_NORMAL +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); #endif -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); #endif -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) #endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); #endif -#ifdef APPLY_SPECULAR +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); -#else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); #endif -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); #endif -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); -#else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP #endif +} -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) + +uniform float u_OutlineHeight; + +void main(void) { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); -} -#endif -#else -color = color * myhalf4(gl_Color.rgba); + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + Position += vec4(Normal * u_OutlineHeight, 0.0); + gl_Position = u_ModelViewProjectionMatrix * Position; + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG + myhalf4 tempColor = myhalf4(1.0); + FogGen(Position, tempColor, myhalf2(0.0, 1.0)); + outColor.rgb = mix(u_Fog.Color, outColor.rgb, tempColor.a); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); -#else -gl_FragColor = vec4(color); + qf_FrontColor = vec4(outColor); +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform float u_OutlineCutOff; + +void main(void) +{ +#ifdef APPLY_OUTLINES_CUTOFF + if (u_OutlineCutOff > 0.0 && (gl_FragCoord.z / gl_FragCoord.w > u_OutlineCutOff)) + discard; #endif + qf_FragColor = vec4(qf_FrontColor); } #endif // FRAGMENT_SHADER diff --git a/shaders/warsow/73.shader_test b/shaders/warsow/73.shader_test index 6e68fc9..879331b 100644 --- a/shaders/warsow/73.shader_test +++ b/shaders/warsow/73.shader_test @@ -1,487 +1,1801 @@ [require] GLSL >= 1.10 +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 2 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_DECAL +#define APPLY_HALFLAMBERT + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + [fragment shader] -#define FRAGMENT_SHADER -#define APPLY_LIGHTSTYLE0 -#define APPLY_FBLIGHTMAP -#define APPLY_SPECULAR -// Warsow GLSL shader +#version 130 -#if !defined(__GLSL_CG_DATA_TYPES) +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -void main() +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; -#endif -#endif -#endif -#endif +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; -#endif +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; -#endif +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; -#endif +vec4 DQReal1, DQDual1; +float scale; -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +if (numWeights > 2) { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} } +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -void main() -{ -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#define NUM_BONE_INFLUENCES 2 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_DECAL +#define APPLY_HALFLAMBERT -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +uniform float u_ShaderTime; -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); -#else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; -#endif +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; -#endif +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors -// deluxemapping using light vectors in modelspace +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; -#ifdef APPLY_LIGHTSTYLE0 +uniform myhalf2 u_BlendMix; -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +uniform float u_MirrorSide; -#define NORMALIZE_DIFFUSE_NORMAL +uniform float u_ZNear, u_ZFar; -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); -#endif +uniform ivec4 u_Viewport; // x, y, width, height -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; -#endif +uniform vec4 u_TextureParams; -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); +uniform myhalf u_SoftParticlesScale; -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) #endif -#endif -#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); -#ifdef APPLY_SPECULAR + falloff *= falloff; -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) #else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); #endif -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); -#else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); #endif -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) +#ifdef APPLY_FOG +struct Fog { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); -} + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) #endif -#else -color = color * myhalf4(gl_Color.rgba); +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); -#else -gl_FragColor = vec4(color); +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif } -#endif // FRAGMENT_SHADER +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); -[vertex shader] -#define VERTEX_SHADER -#define APPLY_LIGHTSTYLE0 -#define APPLY_FBLIGHTMAP -#define APPLY_SPECULAR -// Warsow GLSL shader +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} -#if !defined(__GLSL_CG_DATA_TYPES) -#define myhalf float -#define myhalf2 vec2 -#define myhalf3 vec3 -#define myhalf4 vec4 -#else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 #endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; #endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; #endif +qf_varying vec3 v_Position; + #if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +qf_varying vec3 v_EyeVector; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; -#endif +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif #ifdef VERTEX_SHADER -// Vertex shader +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif -uniform vec3 EyeOrigin; +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} -void main() +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) { -gl_FrontColor = gl_Color; - -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) #endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); #endif -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); #endif -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); #endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP #endif } -#endif // VERTEX_SHADER +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); -#ifdef FRAGMENT_SHADER -// Fragment shader + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; + qf_FrontColor = vec4(outColor); -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; #endif -#endif -#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; #endif -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; #ifdef APPLY_DECAL -uniform sampler2D DecalTexture; +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; #endif #if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; +uniform float u_OffsetMappingScale; #endif -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; #endif -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor #if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) // The following reliefmapping and offsetmapping routine was taken from DarkPlaces @@ -489,207 +1803,259 @@ uniform myhalf GlossExponent; // gloss exponent factor vec2 OffsetMapping(vec2 TexCoord) { #ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING } -#endif +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) void main() { #if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; #endif -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; + myhalf3 weightedDiffuseNormalModelspace; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); #ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); #else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; -#endif +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; #endif -// deluxemapping using light vectors in modelspace +#endif // APPLY_CELSHADING -#ifdef APPLY_LIGHTSTYLE0 +#endif // APPLY_DIRECTIONAL_LIGHT -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); #ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); #else - #define NORMALIZE_DIFFUSE_NORMAL - -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); -#endif + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP #ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; -#endif - -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); - -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); - -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); - -#endif -#endif -#endif + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); #endif #ifdef APPLY_SPECULAR #ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); #else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); #endif -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); -#endif + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); #else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); -#endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); #endif +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + #ifdef APPLY_DECAL + #ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); #else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) -{ -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); -} -#endif + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + #else -color = color * myhalf4(gl_Color.rgba); -#endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; #else -gl_FragColor = vec4(color); + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); #endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); } #endif // FRAGMENT_SHADER - diff --git a/shaders/warsow/76.shader_test b/shaders/warsow/76.shader_test index de4bd35..6e73a4e 100644 --- a/shaders/warsow/76.shader_test +++ b/shaders/warsow/76.shader_test @@ -1,695 +1,1239 @@ [require] GLSL >= 1.10 -[fragment shader] -#define FRAGMENT_SHADER -#define APPLY_LIGHTSTYLE0 -#define APPLY_FBLIGHTMAP -#define APPLY_SPECULAR -#define APPLY_AMBIENT_COMPENSATION -// Warsow GLSL shader - -#if !defined(__GLSL_CG_DATA_TYPES) +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 #endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -void main() +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; -#endif -#endif -#endif -#endif +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; -#endif +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; -#endif +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; -#endif +vec4 DQReal1, DQDual1; +float scale; -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +if (numWeights > 2) { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} } + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -void main() -{ -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#define NUM_BONE_INFLUENCES 2 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +uniform float u_ShaderTime; -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); -#else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) #endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -// deluxemapping using light vectors in modelspace +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} -#ifdef APPLY_LIGHTSTYLE0 -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif -#define NORMALIZE_DIFFUSE_NORMAL +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); #endif -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); #endif -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) #endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); #endif -#ifdef APPLY_SPECULAR +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); -#else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); #endif -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); #endif -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); -#else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP #endif +} -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) + +uniform float u_OutlineHeight; + +void main(void) { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); -} -#endif -#else -color = color * myhalf4(gl_Color.rgba); + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + Position += vec4(Normal * u_OutlineHeight, 0.0); + gl_Position = u_ModelViewProjectionMatrix * Position; + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG + myhalf4 tempColor = myhalf4(1.0); + FogGen(Position, tempColor, myhalf2(0.0, 1.0)); + outColor.rgb = mix(u_Fog.Color, outColor.rgb, tempColor.a); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); -#else -gl_FragColor = vec4(color); + qf_FrontColor = vec4(outColor); +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform float u_OutlineCutOff; + +void main(void) +{ +#ifdef APPLY_OUTLINES_CUTOFF + if (u_OutlineCutOff > 0.0 && (gl_FragCoord.z / gl_FragCoord.w > u_OutlineCutOff)) + discard; #endif + qf_FragColor = vec4(qf_FrontColor); } #endif // FRAGMENT_SHADER -[vertex shader] -#define VERTEX_SHADER -#define APPLY_LIGHTSTYLE0 -#define APPLY_FBLIGHTMAP -#define APPLY_SPECULAR -#define APPLY_AMBIENT_COMPENSATION -// Warsow GLSL shader +[fragment shader] +#version 130 -#if !defined(__GLSL_CG_DATA_TYPES) +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 #endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -void main() +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; -#endif -#endif -#endif -#endif +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; -#endif +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; -#endif +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; -#endif +vec4 DQReal1, DQDual1; +float scale; -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +if (numWeights > 2) { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} } +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -void main() -{ -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#define NUM_BONE_INFLUENCES 2 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +uniform float u_ShaderTime; -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); -#else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) #endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -// deluxemapping using light vectors in modelspace +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} -#ifdef APPLY_LIGHTSTYLE0 -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif -#define NORMALIZE_DIFFUSE_NORMAL +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); #endif -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); #endif -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) #endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); #endif -#ifdef APPLY_SPECULAR +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); -#else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); #endif -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); #endif -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); -#else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP #endif +} -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) + +uniform float u_OutlineHeight; + +void main(void) { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); -} -#endif -#else -color = color * myhalf4(gl_Color.rgba); + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + vec2 TexCoord = a_TexCoord; + myhalf4 inColor = myhalf4(a_Color); + + TransformVerts(Position, Normal, TexCoord); + + Position += vec4(Normal * u_OutlineHeight, 0.0); + gl_Position = u_ModelViewProjectionMatrix * Position; + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG + myhalf4 tempColor = myhalf4(1.0); + FogGen(Position, tempColor, myhalf2(0.0, 1.0)); + outColor.rgb = mix(u_Fog.Color, outColor.rgb, tempColor.a); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); -#else -gl_FragColor = vec4(color); + qf_FrontColor = vec4(outColor); +} + +#endif // VERTEX_SHADER + + +#ifdef FRAGMENT_SHADER +// Fragment shader + +uniform float u_OutlineCutOff; + +void main(void) +{ +#ifdef APPLY_OUTLINES_CUTOFF + if (u_OutlineCutOff > 0.0 && (gl_FragCoord.z / gl_FragCoord.w > u_OutlineCutOff)) + discard; #endif + qf_FragColor = vec4(qf_FrontColor); } #endif // FRAGMENT_SHADER diff --git a/shaders/warsow/79.shader_test b/shaders/warsow/79.shader_test index 4a2358e..27bb40d 100644 --- a/shaders/warsow/79.shader_test +++ b/shaders/warsow/79.shader_test @@ -1,485 +1,1801 @@ [require] GLSL >= 1.10 +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_LIGHTMAPS 1 +#define APPLY_FBLIGHTMAP +#define APPLY_SPECULAR +#define APPLY_RELIEFMAPPING + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + [fragment shader] -#define FRAGMENT_SHADER -#define APPLY_DIRECTIONAL_LIGHT -#define APPLY_CELLSHADING -// Warsow GLSL shader +#version 130 -#if !defined(__GLSL_CG_DATA_TYPES) +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D #endif -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 #endif -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -uniform vec3 EyeOrigin; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -void main() +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; -#endif -#endif -#endif -#endif +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -} +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#endif // VERTEX_SHADER +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -#ifdef FRAGMENT_SHADER -// Fragment shader +vec4 DQReal1, DQDual1; +float scale; -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; -#ifdef APPLY_DECAL -uniform sampler2D DecalTexture; -#endif +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; -#endif +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; -#endif +vec4 DQReal1, DQDual1; +float scale; -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// The following reliefmapping and offsetmapping routine was taken from DarkPlaces -// The credit goes to LordHavoc (as always) -vec2 OffsetMapping(vec2 TexCoord) +if (numWeights > 2) { -#ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} } +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif -void main() -{ -#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; +} + #endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} -#ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_LIGHTMAPS 1 +#define APPLY_FBLIGHTMAP +#define APPLY_SPECULAR +#define APPLY_RELIEFMAPPING -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); +uniform float u_ShaderTime; -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); -#else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; -#endif +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; -#endif +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors -// deluxemapping using light vectors in modelspace +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; -#ifdef APPLY_LIGHTSTYLE0 +uniform myhalf2 u_BlendMix; -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) -#ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); -#else +uniform float u_MirrorSide; -#define NORMALIZE_DIFFUSE_NORMAL +uniform float u_ZNear, u_ZFar; -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); -#endif +uniform ivec4 u_Viewport; // x, y, width, height -#ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; -#endif +uniform vec4 u_TextureParams; -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); +uniform myhalf u_SoftParticlesScale; -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) #endif -#endif -#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); -#ifdef APPLY_SPECULAR + falloff *= falloff; -#ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) #else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); #endif -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); -#else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); #endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); #endif -#ifdef APPLY_DECAL -#ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); -#else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) +#ifdef APPLY_FOG +struct Fog { -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); -} + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) #endif -#else -color = color * myhalf4(gl_Color.rgba); +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); -#else -gl_FragColor = vec4(color); +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif } -#endif // FRAGMENT_SHADER +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); -[vertex shader] -#define VERTEX_SHADER -#define APPLY_DIRECTIONAL_LIGHT -#define APPLY_CELLSHADING -// Warsow GLSL shader +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} -#if !defined(__GLSL_CG_DATA_TYPES) -#define myhalf float -#define myhalf2 vec2 -#define myhalf3 vec3 -#define myhalf4 vec4 -#else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 #endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} -varying vec2 TexCoord; -#ifdef APPLY_LIGHTSTYLE0 -varying vec4 LightmapTexCoord01; -#ifdef APPLY_LIGHTSTYLE2 -varying vec4 LightmapTexCoord23; #endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; #endif +qf_varying vec3 v_Position; + #if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -varying vec3 EyeVector; +qf_varying vec3 v_EyeVector; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -varying vec3 LightVector; -#endif +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) -varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif #ifdef VERTEX_SHADER -// Vertex shader +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif -uniform vec3 EyeOrigin; +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform vec3 LightDir; +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} -void main() +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) { -gl_FrontColor = gl_Color; - -TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0); +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif -#ifdef APPLY_LIGHTSTYLE0 -LightmapTexCoord01.st = gl_MultiTexCoord4.st; -#ifdef APPLY_LIGHTSTYLE1 -LightmapTexCoord01.pq = gl_MultiTexCoord5.st; -#ifdef APPLY_LIGHTSTYLE2 -LightmapTexCoord23.st = gl_MultiTexCoord6.st; -#ifdef APPLY_LIGHTSTYLE3 -LightmapTexCoord23.pq = gl_MultiTexCoord7.st; +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); #endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) #endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); #endif -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif -#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz; -EyeVector = EyeVectorWorld * strMatrix; #endif -#ifdef APPLY_DIRECTIONAL_LIGHT -LightVector = LightDir * strMatrix; +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); #endif -gl_Position = ftransform (); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); #endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP #endif } -#endif // VERTEX_SHADER +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); -#ifdef FRAGMENT_SHADER -// Fragment shader + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); -#ifdef APPLY_LIGHTSTYLE0 -uniform sampler2D LightmapTexture0; -uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord -uniform myhalf3 lsColor0; // lightstyle color +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG -#ifdef APPLY_LIGHTSTYLE1 -uniform sampler2D LightmapTexture1; -uniform float DeluxemapOffset1; -uniform myhalf3 lsColor1; + qf_FrontColor = vec4(outColor); -#ifdef APPLY_LIGHTSTYLE2 -uniform sampler2D LightmapTexture2; -uniform float DeluxemapOffset2; -uniform myhalf3 lsColor2; + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); -#ifdef APPLY_LIGHTSTYLE3 -uniform sampler2D LightmapTexture3; -uniform float DeluxemapOffset3; -uniform myhalf3 lsColor3; +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; #endif -#endif -#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; #endif -uniform sampler2D BaseTexture; -uniform sampler2D NormalmapTexture; -uniform sampler2D GlossTexture; +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; #ifdef APPLY_DECAL -uniform sampler2D DecalTexture; +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; #endif #if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -uniform float OffsetMappingScale; +uniform float u_OffsetMappingScale; #endif -uniform myhalf3 LightAmbient; -#ifdef APPLY_DIRECTIONAL_LIGHT -uniform myhalf3 LightDiffuse; +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; #endif -uniform myhalf GlossIntensity; // gloss scaling factor -uniform myhalf GlossExponent; // gloss exponent factor +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor #if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) // The following reliefmapping and offsetmapping routine was taken from DarkPlaces @@ -487,207 +1803,259 @@ uniform myhalf GlossExponent; // gloss exponent factor vec2 OffsetMapping(vec2 TexCoord) { #ifdef APPLY_RELIEFMAPPING -// 14 sample relief mapping: linear search and then binary search -// this basically steps forward a small amount repeatedly until it finds -// itself inside solid, then jitters forward and back using decreasing -// amounts to find the impact -//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1); -//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1); -vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1); -vec3 RT = vec3(TexCoord, 1); -OffsetVector *= 0.1; -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); -RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); -return RT.xy; -#else -// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) -// this basically moves forward the full distance, and then backs up based -// on height of samples -//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1)); -//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1)); -vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1)); -TexCoord += OffsetVector; -OffsetVector *= 0.5; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a; -return TexCoord; -#endif + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING } -#endif +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) void main() { #if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -// apply offsetmapping -vec2 TexCoordOffset = OffsetMapping(TexCoord); -#define TexCoord TexCoordOffset + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset #endif -myhalf3 surfaceNormal; -myhalf3 diffuseNormalModelspace; -myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0); -float diffuseProduct; -#ifdef APPLY_CELLSHADING -int lightcell; -float diffuseProductPositive; -float diffuseProductNegative; -float hardShadow; + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; #endif -myhalf3 weightedDiffuseNormal; -myhalf3 specularNormal; -float specularProduct; + myhalf3 weightedDiffuseNormalModelspace; -#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0) -myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); #else -myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); #endif -// get the surface normal -surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5)); + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); #ifdef APPLY_DIRECTIONAL_LIGHT -diffuseNormal = myhalf3 (LightVector); -weightedDiffuseNormal = diffuseNormal; -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -#ifdef APPLY_CELLSHADING -hardShadow = 0.0; -diffuseProductPositive = max (diffuseProduct, 0.0); -diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); -// smooth the hard shadow edge -lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); -hardShadow += float(lightcell); +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); -lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); -hardShadow += float(lightcell); + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); -lightcell = int(diffuseProductPositive * 2.0); -hardShadow += float(lightcell); + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); -color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); -// backlight -lightcell = int (diffuseProductNegative * 2.0); -color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); #else -color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb; -#endif +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; #endif -// deluxemapping using light vectors in modelspace +#endif // APPLY_CELSHADING -#ifdef APPLY_LIGHTSTYLE0 +#endif // APPLY_DIRECTIONAL_LIGHT -// get light normal -diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -// calculate directional shading -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); #ifdef APPLY_FBLIGHTMAP -weightedDiffuseNormal = diffuseNormal; -// apply lightmap color -color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st))); + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); #else - #define NORMALIZE_DIFFUSE_NORMAL - -weightedDiffuseNormal = lsColor0 * diffuseNormal; -// apply lightmap color -color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture0, LightmapTexCoord01.st)); -#endif + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP #ifdef APPLY_AMBIENT_COMPENSATION -// compensate for ambient lighting -color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient; -#endif - -#ifdef APPLY_LIGHTSTYLE1 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor1 * diffuseNormal; -color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture1, LightmapTexCoord01.pq)); - -#ifdef APPLY_LIGHTSTYLE2 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5); -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor2 * diffuseNormal; -color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture2, LightmapTexCoord23.st)); - -#ifdef APPLY_LIGHTSTYLE3 -diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);; -diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2])))); -diffuseProduct = float (dot (surfaceNormal, diffuseNormal)); -weightedDiffuseNormal += lsColor3 * diffuseNormal; -color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (texture2D (LightmapTexture3, LightmapTexCoord23.pq)); - -#endif -#endif -#endif + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); #endif #ifdef APPLY_SPECULAR #ifdef NORMALIZE_DIFFUSE_NORMAL -specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector))); + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); #else -specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector))); + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); #endif -specularProduct = float (dot (surfaceNormal, specularNormal)); -color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord)) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent); -#endif + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR -#ifdef APPLY_BASETEX_ALPHA_ONLY -color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a)); +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); #else -#ifdef APPLY_COLOR_CLAMPING -color = min(color, myhalf4(1.0)); -#endif -color = color * myhalf4(texture2D(BaseTexture, TexCoord)); + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); #endif +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + #ifdef APPLY_DECAL + #ifdef APPLY_DECAL_ADD -myhalf3 decal = myhalf3(gl_Color.rgb) * myhalf3(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb + color.rgb; -color.a = color.a * myhalf(gl_Color.a); + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); #else -myhalf4 decal = myhalf4(gl_Color.rgba); -if (decal.a > 0.0) -{ -decal = decal * myhalf4(texture2D(DecalTexture, TexCoord)); -color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a); -} -#endif + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + #else -color = color * myhalf4(gl_Color.rgba); -#endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),color.a); +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; #else -gl_FragColor = vec4(color); + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); #endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); } #endif // FRAGMENT_SHADER - diff --git a/shaders/warsow/82.shader_test b/shaders/warsow/82.shader_test index 76c961a..14f0ec4 100644 --- a/shaders/warsow/82.shader_test +++ b/shaders/warsow/82.shader_test @@ -1,307 +1,2059 @@ [require] GLSL >= 1.10 +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_LIGHTMAPS 1 +#define APPLY_FBLIGHTMAP +#define APPLY_RELIEFMAPPING + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + [fragment shader] -#define FRAGMENT_SHADER -// Warsow GLSL shader +#version 130 -#if !defined(__GLSL_CG_DATA_TYPES) +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} -varying vec4 TexCoord; -varying vec4 ProjVector; -#ifdef APPLY_EYEDOT -varying vec3 EyeVector; +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) #endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; -#ifdef APPLY_EYEDOT -uniform vec3 EyeOrigin; -uniform float FrontPlane; +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; -void main(void) +if (numWeights > 1) { -gl_FrontColor = gl_Color; +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -mat4 textureMatrix; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -textureMatrix = gl_TextureMatrix[0]; -TexCoord.st = vec2 (textureMatrix * gl_MultiTexCoord0); +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -textureMatrix = gl_TextureMatrix[0]; -textureMatrix[0] = -textureMatrix[0]; -textureMatrix[1] = -textureMatrix[1]; -TexCoord.pq = vec2 (textureMatrix * gl_MultiTexCoord0); +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; -#ifdef APPLY_EYEDOT -mat3 strMatrix; -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif -vec3 EyeVectorWorld = (EyeOrigin - gl_Vertex.xyz) * FrontPlane; -EyeVector = EyeVectorWorld * strMatrix; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} + +// use defines to overload the transform function -gl_Position = ftransform(); -ProjVector = gl_Position; -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) #endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} } -#endif // VERTEX_SHADER +float len = length(DQReal); +DQReal /= len; +DQDual /= len; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; -#ifdef FRAGMENT_SHADER -// Fragment shader +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif -#ifdef APPLY_DUDV -uniform sampler2D DuDvMapTexture; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif +} -#ifdef APPLY_EYEDOT -uniform sampler2D NormalmapTexture; +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) #endif -uniform sampler2D ReflectionTexture; -uniform sampler2D RefractionTexture; -uniform float TextureWidth, TextureHeight; +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; -void main(void) +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) { -myhalf3 color; +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) -#ifdef APPLY_DUDV -vec3 displacement = vec3(texture2D(DuDvMapTexture, vec2(TexCoord.pq) * vec2(0.25))); -vec2 coord = vec2(TexCoord.st) + vec2(displacement) * vec2 (0.2); +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -vec3 fdist = vec3 (normalize(vec3(texture2D(DuDvMapTexture, coord)) - vec3 (0.5))) * vec3(0.005); +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] #else -vec3 fdist = vec3(0.0); +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + #endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_LIGHTMAPS 1 +#define APPLY_FBLIGHTMAP +#define APPLY_RELIEFMAPPING + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors -// get projective texcoords -float scale = float(1.0 / float(ProjVector.w)); -float inv2NW = 1.0 / (2.0 * float (TextureWidth)); -float inv2NH = 1.0 / (2.0 * float (TextureHeight)); -vec2 projCoord = (vec2(ProjVector.xy) * scale + vec2 (1.0)) * vec2 (0.5) + vec2(fdist.xy); -projCoord.s = float (clamp (float(projCoord.s), inv2NW, 1.0 - inv2NW)); -projCoord.t = float (clamp (float(projCoord.t), inv2NH, 1.0 - inv2NH)); +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; +uniform myhalf2 u_BlendMix; -myhalf3 refr = myhalf3(0.0); -myhalf3 refl = myhalf3(0.0); +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) -#ifdef APPLY_EYEDOT -// calculate dot product between the surface normal and eye vector -// great for simulating varying water translucency based on the view angle -myhalf3 surfaceNormal = normalize(myhalf3(texture2D(NormalmapTexture, coord)) - myhalf3 (0.5)); -vec3 eyeNormal = normalize(myhalf3(EyeVector)); +uniform float u_MirrorSide; -float refrdot = float(dot(surfaceNormal, eyeNormal)); -//refrdot = float (clamp (refrdot, 0.0, 1.0)); -float refldot = 1.0 - refrdot; -// get refraction and reflection +uniform float u_ZNear, u_ZFar; -#ifdef APPLY_REFRACTION -refr = (myhalf3(texture2D(RefractionTexture, projCoord))) * refrdot; +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) #endif -#ifdef APPLY_REFLECTION -refl = (myhalf3(texture2D(ReflectionTexture, projCoord))) * refldot; + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) #else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif -#ifdef APPLY_REFRACTION -refr = (myhalf3(texture2D(RefractionTexture, projCoord))); +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) #endif -#ifdef APPLY_REFLECTION -refl = (myhalf3(texture2D(ReflectionTexture, projCoord))); +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif +} -// add reflection and refraction -#ifdef APPLY_DISTORTION_ALPHA -color = myhalf3(gl_Color.rgb) + myhalf3(mix (refr, refl, float(gl_Color.a))); -#else -color = myhalf3(gl_Color.rgb) + refr + refl; + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),1.0); -#else -gl_FragColor = vec4(vec3(color),1.0); +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); #endif } -#endif // FRAGMENT_SHADER +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} +#endif -[vertex shader] -#define VERTEX_SHADER -// Warsow GLSL shader +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif -#if !defined(__GLSL_CG_DATA_TYPES) -#define myhalf float -#define myhalf2 vec2 -#define myhalf3 vec3 -#define myhalf4 vec4 -#else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; #endif -varying vec4 TexCoord; -varying vec4 ProjVector; -#ifdef APPLY_EYEDOT -varying vec3 EyeVector; +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; #endif #ifdef VERTEX_SHADER -// Vertex shader +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -#ifdef APPLY_EYEDOT -uniform vec3 EyeOrigin; -uniform float FrontPlane; +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); #endif +} -void main(void) +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) { -gl_FrontColor = gl_Color; +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -mat4 textureMatrix; +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif -textureMatrix = gl_TextureMatrix[0]; -TexCoord.st = vec2 (textureMatrix * gl_MultiTexCoord0); +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif -textureMatrix = gl_TextureMatrix[0]; -textureMatrix[0] = -textureMatrix[0]; -textureMatrix[1] = -textureMatrix[1]; -TexCoord.pq = vec2 (textureMatrix * gl_MultiTexCoord0); +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif -#ifdef APPLY_EYEDOT -mat3 strMatrix; -strMatrix[0] = gl_MultiTexCoord1.xyz; -strMatrix[2] = gl_Normal.xyz; -strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]); +#endif -vec3 EyeVectorWorld = (EyeOrigin - gl_Vertex.xyz) * FrontPlane; -EyeVector = EyeVectorWorld * strMatrix; +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); #endif -gl_Position = ftransform(); -ProjVector = gl_Position; -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); #endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP #endif } -#endif // VERTEX_SHADER +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER #ifdef FRAGMENT_SHADER // Fragment shader -#ifdef APPLY_DUDV -uniform sampler2D DuDvMapTexture; +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; #endif -#ifdef APPLY_EYEDOT -uniform sampler2D NormalmapTexture; +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; #endif -uniform sampler2D ReflectionTexture; -uniform sampler2D RefractionTexture; -uniform float TextureWidth, TextureHeight; -void main(void) +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() { -myhalf3 color; +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif -#ifdef APPLY_DUDV -vec3 displacement = vec3(texture2D(DuDvMapTexture, vec2(TexCoord.pq) * vec2(0.25))); -vec2 coord = vec2(TexCoord.st) + vec2(displacement) * vec2 (0.2); + myhalf3 weightedDiffuseNormalModelspace; -vec3 fdist = vec3 (normalize(vec3(texture2D(DuDvMapTexture, coord)) - vec3 (0.5))) * vec3(0.005); +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); #else -vec3 fdist = vec3(0.0); + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); #endif -// get projective texcoords -float scale = float(1.0 / float(ProjVector.w)); -float inv2NW = 1.0 / (2.0 * float (TextureWidth)); -float inv2NH = 1.0 / (2.0 * float (TextureHeight)); -vec2 projCoord = (vec2(ProjVector.xy) * scale + vec2 (1.0)) * vec2 (0.5) + vec2(fdist.xy); -projCoord.s = float (clamp (float(projCoord.s), inv2NW, 1.0 - inv2NW)); -projCoord.t = float (clamp (float(projCoord.t), inv2NH, 1.0 - inv2NH)); + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); -myhalf3 refr = myhalf3(0.0); -myhalf3 refl = myhalf3(0.0); +#ifdef APPLY_DIRECTIONAL_LIGHT -#ifdef APPLY_EYEDOT -// calculate dot product between the surface normal and eye vector -// great for simulating varying water translucency based on the view angle -myhalf3 surfaceNormal = normalize(myhalf3(texture2D(NormalmapTexture, coord)) - myhalf3 (0.5)); -vec3 eyeNormal = normalize(myhalf3(EyeVector)); +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT -float refrdot = float(dot(surfaceNormal, eyeNormal)); -//refrdot = float (clamp (refrdot, 0.0, 1.0)); -float refldot = 1.0 - refrdot; -// get refraction and reflection + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); -#ifdef APPLY_REFRACTION -refr = (myhalf3(texture2D(RefractionTexture, projCoord))) * refrdot; -#endif -#ifdef APPLY_REFLECTION -refl = (myhalf3(texture2D(ReflectionTexture, projCoord))) * refldot; -#endif + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; #else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); -#ifdef APPLY_REFRACTION -refr = (myhalf3(texture2D(RefractionTexture, projCoord))); +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; #endif -#ifdef APPLY_REFLECTION -refl = (myhalf3(texture2D(ReflectionTexture, projCoord))); + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); #endif +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); #endif -// add reflection and refraction -#ifdef APPLY_DISTORTION_ALPHA -color = myhalf3(gl_Color.rgb) + myhalf3(mix (refr, refl, float(gl_Color.a))); + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); #else -color = myhalf3(gl_Color.rgb) + refr + refl; + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); #endif -#ifdef APPLY_GRAYSCALE -float grey = dot(color, myhalf3(0.299, 0.587, 0.114)); -gl_FragColor = vec4(vec3(grey),1.0); +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; #else -gl_FragColor = vec4(vec3(color),1.0); + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); #endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); } #endif // FRAGMENT_SHADER - diff --git a/shaders/warsow/85.shader_test b/shaders/warsow/85.shader_test index 9b644bc..d2d1c57 100644 --- a/shaders/warsow/85.shader_test +++ b/shaders/warsow/85.shader_test @@ -1,225 +1,2059 @@ [require] GLSL >= 1.10 +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_RELIEFMAPPING +#define APPLY_DIRECTIONAL_LIGHT_MIX + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + [fragment shader] -#define FRAGMENT_SHADER -// Warsow GLSL shader +#version 130 -#if !defined(__GLSL_CG_DATA_TYPES) +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} -varying vec4 ProjVector; +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; -void main(void) +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) { -gl_FrontColor = gl_Color; +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -mat4 textureMatrix; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; -textureMatrix = gl_TextureMatrix[0]; +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif -gl_Position = ftransform(); -ProjVector = textureMatrix * gl_Vertex; +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif } -#endif // VERTEX_SHADER +// use defines to overload the transform function +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; -#ifdef FRAGMENT_SHADER -// Fragment shader +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) -uniform myhalf3 LightAmbient; +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; -uniform float TextureWidth, TextureHeight; -uniform float ProjDistance; -uniform sampler2DShadow ShadowmapTexture; +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif -void main(void) +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) { -myhalf color = myhalf(1.0); +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} -if (ProjVector.w <= 0.0 || ProjVector.w >= ProjDistance) -discard; +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_RELIEFMAPPING +#define APPLY_DIRECTIONAL_LIGHT_MIX + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; -float dtW = 1.0 / TextureWidth; -float dtH = 1.0 / TextureHeight; +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; -vec3 coord = vec3 (ProjVector.xyz / ProjVector.w); -coord = (coord + vec3 (1.0)) * vec3 (0.5); -coord.s = float (clamp (float(coord.s), dtW, 1.0 - dtW)); -coord.t = float (clamp (float(coord.t), dtH, 1.0 - dtH)); -coord.r = float (clamp (float(coord.r), 0.0, 1.0)); +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; -myhalf shadow0 = myhalf(shadow2D(ShadowmapTexture, coord).r); -myhalf shadow = shadow0; +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors -#if defined(APPLY_PCF2x2) || defined(APPLY_PCF3x3) +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; -vec3 coord2 = coord + vec3(0.0, dtH, 0.0); -myhalf shadow1 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +uniform myhalf2 u_BlendMix; -coord2 = coord + vec3(dtW, dtH, 0.0); -myhalf shadow2 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) -coord2 = coord + vec3(dtW, 0.0, 0.0); -myhalf shadow3 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +uniform float u_MirrorSide; -#if defined(APPLY_PCF3x3) -coord2 = coord + vec3(-dtW, 0.0, 0.0); -myhalf shadow4 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +uniform float u_ZNear, u_ZFar; -coord2 = coord + vec3(-dtW, -dtH, 0.0); -myhalf shadow5 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +uniform ivec4 u_Viewport; // x, y, width, height -coord2 = coord + vec3(0.0, -dtH, 0.0); -myhalf shadow6 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +uniform vec4 u_TextureParams; -coord2 = coord + vec3(dtW, -dtH, 0.0); -myhalf shadow7 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +uniform myhalf u_SoftParticlesScale; -coord2 = coord + vec3(-dtW, dtH, 0.0); -myhalf shadow8 = myhalf (shadow2D (ShadowmapTexture, coord2).r); -shadow = (shadow0 + shadow1 + shadow2 + shadow3 + shadow4 + shadow5 + shadow6 + shadow7 + shadow8) * myhalf(0.11); +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) #else -shadow = (shadow0 + shadow1 + shadow2 + shadow3) * myhalf(0.25); +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) #else -shadow = shadow0; + for (int i = 0; i < NUM_DLIGHTS; i++) #endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); -float attenuation = float (ProjVector.w) / ProjDistance; -myhalf compensation = myhalf(0.25) - max(LightAmbient.x, max(LightAmbient.y, LightAmbient.z)) -;compensation = max (compensation, 0.0); -color = shadow + attenuation + compensation; + falloff *= falloff; -gl_FragColor = vec4(vec3(color),1.0); -} + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif -#endif // FRAGMENT_SHADER + Color += falloff * u_DynamicLights[i].Diffuse; + } + return Color; +} -[vertex shader] -#define VERTEX_SHADER -// Warsow GLSL shader -#if !defined(__GLSL_CG_DATA_TYPES) -#define myhalf float -#define myhalf2 vec2 -#define myhalf3 vec3 -#define myhalf4 vec4 +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif #endif -varying vec4 ProjVector; +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif #ifdef VERTEX_SHADER -// Vertex shader +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif -void main(void) +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) { -gl_FrontColor = gl_Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif +#endif -mat4 textureMatrix; +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif -textureMatrix = gl_TextureMatrix[0]; +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif -gl_Position = ftransform(); -ProjVector = textureMatrix * gl_Vertex; + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif } -#endif // VERTEX_SHADER +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER #ifdef FRAGMENT_SHADER // Fragment shader -uniform myhalf3 LightAmbient; +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor -uniform float TextureWidth, TextureHeight; -uniform float ProjDistance; -uniform sampler2DShadow ShadowmapTexture; +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -void main(void) +void main() { -myhalf color = myhalf(1.0); +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); -if (ProjVector.w <= 0.0 || ProjVector.w >= ProjDistance) -discard; + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); -float dtW = 1.0 / TextureWidth; -float dtH = 1.0 / TextureHeight; + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT -vec3 coord = vec3 (ProjVector.xyz / ProjVector.w); -coord = (coord + vec3 (1.0)) * vec3 (0.5); -coord.s = float (clamp (float(coord.s), dtW, 1.0 - dtW)); -coord.t = float (clamp (float(coord.t), dtH, 1.0 - dtH)); -coord.r = float (clamp (float(coord.r), 0.0, 1.0)); +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif -myhalf shadow0 = myhalf(shadow2D(ShadowmapTexture, coord).r); -myhalf shadow = shadow0; +#endif // APPLY_CELSHADING -#if defined(APPLY_PCF2x2) || defined(APPLY_PCF3x3) +#endif // APPLY_DIRECTIONAL_LIGHT -vec3 coord2 = coord + vec3(0.0, dtH, 0.0); -myhalf shadow1 = myhalf (shadow2D (ShadowmapTexture, coord2).r); + // deluxemapping using light vectors in modelspace -coord2 = coord + vec3(dtW, dtH, 0.0); -myhalf shadow2 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); -coord2 = coord + vec3(dtW, 0.0, 0.0); -myhalf shadow3 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif -#if defined(APPLY_PCF3x3) -coord2 = coord + vec3(-dtW, 0.0, 0.0); -myhalf shadow4 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif -coord2 = coord + vec3(-dtW, -dtH, 0.0); -myhalf shadow5 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +#ifdef APPLY_SPECULAR -coord2 = coord + vec3(0.0, -dtH, 0.0); -myhalf shadow6 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif -coord2 = coord + vec3(dtW, -dtH, 0.0); -myhalf shadow7 = myhalf (shadow2D (ShadowmapTexture, coord2).r); + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR -coord2 = coord + vec3(-dtW, dtH, 0.0); -myhalf shadow8 = myhalf (shadow2D (ShadowmapTexture, coord2).r); +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; -shadow = (shadow0 + shadow1 + shadow2 + shadow3 + shadow4 + shadow5 + shadow6 + shadow7 + shadow8) * myhalf(0.11); +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); #else -shadow = (shadow0 + shadow1 + shadow2 + shadow3) * myhalf(0.25); + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); #endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; #else -shadow = shadow0; + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); #endif -float attenuation = float (ProjVector.w) / ProjDistance; -myhalf compensation = myhalf(0.25) - max(LightAmbient.x, max(LightAmbient.y, LightAmbient.z)) -;compensation = max (compensation, 0.0); -color = shadow + attenuation + compensation; +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif -gl_FragColor = vec4(vec3(color),1.0); + qf_FragColor = vec4(color); } #endif // FRAGMENT_SHADER - diff --git a/shaders/warsow/88.shader_test b/shaders/warsow/88.shader_test index b4f6f7c..97d2c67 100644 --- a/shaders/warsow/88.shader_test +++ b/shaders/warsow/88.shader_test @@ -1,103 +1,2061 @@ [require] GLSL >= 1.10 +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_SPECULAR +#define APPLY_RELIEFMAPPING +#define APPLY_DIRECTIONAL_LIGHT_MIX + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + [fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 #define FRAGMENT_SHADER -// Warsow GLSL shader +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; +vec4 DQReal1, DQDual1; +float scale; -varying vec4 ProjVector; +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif #ifdef VERTEX_SHADER -// Vertex shader +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_VERTEX +#define APPLY_ALPHA_VERTEX +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_SPECULAR +#define APPLY_RELIEFMAPPING +#define APPLY_DIRECTIONAL_LIGHT_MIX + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) -uniform float OutlineHeight; +uniform float u_MirrorSide; -void main(void) +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif { -gl_FrontColor = gl_Color; + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} -vec4 n = vec4(gl_Normal.xyz, 0.0); -vec4 v = vec4(gl_Vertex) + n * OutlineHeight; -gl_Position = gl_ModelViewProjectionMatrix * v; -ProjVector = gl_Position; -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * v; +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) #endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) #endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; } -#endif // VERTEX_SHADER +#endif + +#endif +#endif -#ifdef FRAGMENT_SHADER -// Fragment shader +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 -uniform float OutlineCutOff; +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) -void main(void) +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif { + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); -#ifdef APPLY_OUTLINES_CUTOFF -if (OutlineCutOff > 0.0 && (ProjVector.w > OutlineCutOff)) -discard; +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); #endif -gl_FragColor = vec4 (gl_Color); +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif } -#endif // FRAGMENT_SHADER +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); -[vertex shader] -#define VERTEX_SHADER -// Warsow GLSL shader +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) -varying vec4 ProjVector; +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif #ifdef VERTEX_SHADER -// Vertex shader +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} -uniform float OutlineHeight; +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif -void main(void) +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() { -gl_FrontColor = gl_Color; + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; -vec4 n = vec4(gl_Normal.xyz, 0.0); -vec4 v = vec4(gl_Vertex) + n * OutlineHeight; + TransformVerts(Position, Normal, Tangent, TexCoord); -gl_Position = gl_ModelViewProjectionMatrix * v; -ProjVector = gl_Position; -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * v; + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); #endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; #endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; } #endif // VERTEX_SHADER - #ifdef FRAGMENT_SHADER // Fragment shader -uniform float OutlineCutOff; +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) -void main(void) +void main() { +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT -#ifdef APPLY_OUTLINES_CUTOFF -if (OutlineCutOff > 0.0 && (ProjVector.w > OutlineCutOff)) -discard; +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; #endif -gl_FragColor = vec4 (gl_Color); +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); } #endif // FRAGMENT_SHADER - diff --git a/shaders/warsow/91.shader_test b/shaders/warsow/91.shader_test index e32eb19..97a04bf 100644 --- a/shaders/warsow/91.shader_test +++ b/shaders/warsow/91.shader_test @@ -2,56 +2,2062 @@ GLSL >= 1.10 [vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 #define VERTEX_SHADER -// Warsow GLSL shader - -#if !defined(__GLSL_CG_DATA_TYPES) +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) #define myhalf float #define myhalf2 vec2 #define myhalf3 vec3 #define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture #else -#define myhalf half -#define myhalf2 half2 -#define myhalf3 half3 -#define myhalf4 half4 +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 #endif +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI #define M_TWOPI 6.28318530717958647692 +#endif -varying vec2 TexCoord; +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif #ifdef VERTEX_SHADER -// Vertex shader +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -uniform float TurbAmplitude, TurbPhase; +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; -void main(void) +if (numWeights > 3) { -gl_FrontColor = gl_Color; +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} -vec4 turb; -turb = vec4(gl_MultiTexCoord0); -turb.s += TurbAmplitude * sin( ((gl_MultiTexCoord0.t / 4.0 + TurbPhase)) * M_TWOPI ); -turb.t += TurbAmplitude * sin( ((gl_MultiTexCoord0.s / 4.0 + TurbPhase)) * M_TWOPI ); -TexCoord = vec2(gl_TextureMatrix[0] * turb); +float len = length(DQReal); +DQReal /= len; +DQDual /= len; -gl_Position = ftransform(); -#ifdef APPLY_CLIPPING -#ifdef __GLSL_CG_DATA_TYPES -gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; #endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; #endif } -#endif // VERTEX_SHADER +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 4 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_SPECULAR +#define APPLY_HALFLAMBERT +#define APPLY_ENTITY_DECAL + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER #ifdef FRAGMENT_SHADER // Fragment shader -uniform sampler2D BaseTexture; +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif -void main(void) -{ +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define NUM_BONE_INFLUENCES 4 +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_SPECULAR +#define APPLY_HALFLAMBERT +#define APPLY_ENTITY_DECAL + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER diff --git a/shaders/warsow/94.shader_test b/shaders/warsow/94.shader_test new file mode 100644 index 0000000..4cd298b --- /dev/null +++ b/shaders/warsow/94.shader_test @@ -0,0 +1,2059 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_SPECULAR +#define APPLY_HALFLAMBERT + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define APPLY_DIRECTIONAL_LIGHT +#define APPLY_SPECULAR +#define APPLY_HALFLAMBERT + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + diff --git a/shaders/warsow/97.shader_test b/shaders/warsow/97.shader_test new file mode 100644 index 0000000..6dddd6d --- /dev/null +++ b/shaders/warsow/97.shader_test @@ -0,0 +1,2057 @@ +[require] +GLSL >= 1.10 + +[vertex shader] +#version 130 +#extension GL_ARB_draw_instanced : enable +#define QF_GLSL_VERSION 130 +#define VERTEX_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_LIGHTMAPS 1 +#define APPLY_SPECULAR + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + +[fragment shader] +#version 130 + +#define QF_GLSL_VERSION 130 +#define FRAGMENT_SHADER +#if !defined(myhalf) +//#if !defined(__GLSL_CG_DATA_TYPES) +#define myhalf float +#define myhalf2 vec2 +#define myhalf3 vec3 +#define myhalf4 vec4 +//#else +//#define myhalf half +//#define myhalf2 half2 +//#define myhalf3 half3 +//#define myhalf4 half4 +//#endif +#endif + +#if QF_GLSL_VERSION >= 130 + precision highp float; + +# ifdef VERTEX_SHADER + out myhalf4 qf_FrontColor; +# define qf_varying out +# define qf_attribute in +# endif +# ifdef FRAGMENT_SHADER + in myhalf4 qf_FrontColor; + out myhalf4 qf_FragColor; +# define qf_varying in +# define qf_attribute in +# endif + +# define qf_texture texture +# define qf_textureCube texture +# define qf_textureLod textureLod +# define qf_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d)) +# define qf_shadow texture +#else +# ifdef VERTEX_SHADER +# define qf_FrontColor gl_FrontColor +# define qf_varying varying +# define qf_attribute attribute +# endif + +# ifdef FRAGMENT_SHADER +# define qf_FrontColor gl_Color +# define qf_FragColor gl_FragColor +# define qf_varying varying +# define qf_attribute attribute +# endif +# define qf_texture texture2D +# define qf_textureLod texture2DLod +# define qf_textureCube textureCube +# define qf_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d)) +# define qf_shadow shadow2D +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef MAX_UNIFORM_BONES +#define MAX_UNIFORM_BONES 100 +#endif + +#ifndef MAX_UNIFORM_INSTANCES +#define MAX_UNIFORM_INSTANCES 40 +#endif +uniform vec3 u_QF_ViewOrigin; +uniform mat3 u_QF_ViewAxis; +uniform float u_QF_MirrorSide; +uniform vec3 u_QF_EntityOrigin; +uniform float u_QF_ShaderTime; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_TWOPI +#define M_TWOPI 6.28318530717958647692 +#endif + +#ifndef WAVE_SIN +float QF_WaveFunc_Sin(float x) +{ +x -= floor(x); +return sin(x * M_TWOPI); +} +float QF_WaveFunc_Triangle(float x) +{ +x -= floor(x); +return step(x, 0.25) * x * 4.0 + (2.0 - 4.0 * step(0.25, x) * step(x, 0.75) * x) + ((step(0.75, x) * x - 0.75) * 4.0 - 1.0); +} +float QF_WaveFunc_Square(float x) +{ +x -= floor(x); +return step(x, 0.5) * 2.0 - 1.0; +} +float QF_WaveFunc_Sawtooth(float x) +{ +x -= floor(x); +return x; +} +float QF_QF_WaveFunc_InverseSawtooth(float x) +{ +x -= floor(x); +return 1.0 - x; +} + +#define WAVE_SIN(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sin((phase)+(time)*(freq)))) +#define WAVE_TRIANGLE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Triangle((phase)+(time)*(freq)))) +#define WAVE_SQUARE(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Square((phase)+(time)*(freq)))) +#define WAVE_SAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_WaveFunc_Sawtooth((phase)+(time)*(freq)))) +#define WAVE_INVERSESAWTOOTH(time,base,amplitude,phase,freq) (((base)+(amplitude)*QF_QF_WaveFunc_InverseSawtooth((phase)+(time)*(freq)))) +#endif + +#ifdef VERTEX_SHADER +attribute vec4 a_BonesIndices; +attribute vec4 a_BonesWeights; + +uniform vec4 u_QF_DualQuats[MAX_UNIFORM_BONES*2]; + +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +// use defines to overload the transform function + +#define DUAL_QUAT_TRANSFORM_NORMALS +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#define DUAL_QUAT_TRANSFORM_TANGENT +#if defined(DUAL_QUAT_TRANSFORM_NORMALS) +#if defined(DUAL_QUAT_TRANSFORM_TANGENT) +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal, inout vec3 Tangent) +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position, inout vec3 Normal) +#endif +#else +void QF_VertexDualQuatsTransform(const int numWeights, inout vec4 Position) +#endif +{ +int index; +vec4 Indices = a_BonesIndices; +vec4 Weights = a_BonesWeights; +vec4 Indices_2 = Indices * 2.0; +vec4 DQReal, DQDual; + +index = int(Indices_2.x); +DQReal = u_QF_DualQuats[index+0]; +DQDual = u_QF_DualQuats[index+1]; + +if (numWeights > 1) +{ +DQReal *= Weights.x; +DQDual *= Weights.x; + +vec4 DQReal1, DQDual1; +float scale; + +index = int(Indices_2.y); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.y; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 2) +{ +index = int(Indices_2.z); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.z; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; + +if (numWeights > 3) +{ +index = int(Indices_2.w); +DQReal1 = u_QF_DualQuats[index+0]; +DQDual1 = u_QF_DualQuats[index+1]; +// antipodality handling +scale = (dot(DQReal1, DQReal) < 0.0 ? -1.0 : 1.0) * Weights.w; +DQReal += DQReal1 * scale; +DQDual += DQDual1 * scale; +} +} +} + +float len = length(DQReal); +DQReal /= len; +DQDual /= len; + +Position.xyz = (cross(DQReal.xyz, cross(DQReal.xyz, Position.xyz) + Position.xyz*DQReal.w + DQDual.xyz) + DQDual.xyz*DQReal.w - DQReal.xyz*DQDual.w)*2.0 + Position.xyz; + +#ifdef DUAL_QUAT_TRANSFORM_NORMALS +Normal = cross(DQReal.xyz, cross(DQReal.xyz, Normal) + Normal*DQReal.w)*2.0 + Normal; +#endif + +#ifdef DUAL_QUAT_TRANSFORM_TANGENT +Tangent = cross(DQReal.xyz, cross(DQReal.xyz, Tangent) + Tangent*DQReal.w)*2.0 + Tangent; +#endif +} + +#endif +#ifdef VERTEX_SHADER +#ifdef APPLY_INSTANCED_ATTRIB_TRASNFORMS +attribute vec4 a_InstanceQuat; +attribute vec4 a_InstancePosAndScale; +#elif defined(GL_ARB_draw_instanced) + +uniform vec4 u_QF_InstancePoints[MAX_UNIFORM_INSTANCES*2]; + +#define a_InstanceQuat u_QF_InstancePoints[gl_InstanceID*2] +#define a_InstancePosAndScale u_QF_InstancePoints[gl_InstanceID*2+1] +#else +uniform vec4 u_QF_InstancePoints[2]; +#define a_InstanceQuat u_QF_InstancePoints[0] +#define a_InstancePosAndScale u_QF_InstancePoints[1] +#endif + +void QF_InstancedTransform(inout vec4 Position, inout vec3 Normal) +{ +Position.xyz = (cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Position.xyz) + Position.xyz*a_InstanceQuat.w)*2.0 + Position.xyz) * + a_InstancePosAndScale.w + a_InstancePosAndScale.xyz; +Normal = cross(a_InstanceQuat.xyz, cross(a_InstanceQuat.xyz, Normal) + Normal*a_InstanceQuat.w)*2.0 + Normal; +} + +#endif +#define QF_LatLong2Norm(ll) vec3(cos((ll).y) * sin((ll).x), sin((ll).y) * sin((ll).x), cos((ll).x)) + +#define APPLY_RGB_CONST +#define APPLY_ALPHA_CONST +#define NUM_LIGHTMAPS 1 +#define APPLY_SPECULAR + +#define DRAWFLAT_NORMAL_STEP 0.5 // floor or ceiling if < abs(normal.z) +uniform mat4 u_ModelViewMatrix; +uniform mat4 u_ModelViewProjectionMatrix; + +uniform float u_ShaderTime; + +uniform vec3 u_ViewOrigin; +uniform mat3 u_ViewAxis; + +uniform vec3 u_EntityDist; +uniform vec3 u_EntityOrigin; +uniform myhalf4 u_EntityColor; + +uniform myhalf4 u_ConstColor; +uniform myhalf4 u_RGBGenFuncArgs, u_AlphaGenFuncArgs; +uniform myhalf3 u_LightstyleColor[4]; // lightstyle colors + +uniform myhalf3 u_LightAmbient; +uniform myhalf3 u_LightDiffuse; +uniform vec3 u_LightDir; + +uniform myhalf2 u_BlendMix; + +uniform vec2 u_TextureMatrix[3]; +#define TextureMatrix2x3Mul(m2x3,tc) vec2(dot((m2x3)[0],(tc)) + (m2x3)[2][0], dot((m2x3)[1],(tc)) + (m2x3)[2][1]) + +uniform float u_MirrorSide; + +uniform float u_ZNear, u_ZFar; + +uniform ivec4 u_Viewport; // x, y, width, height + +uniform vec4 u_TextureParams; + +uniform myhalf u_SoftParticlesScale; + + +#if defined(NUM_DLIGHTS) +#if defined(FRAGMENT_SHADER) +#if defined(NUM_DLIGHTS) + +struct DynamicLight +{ + myhalf Radius; + vec3 Position; + myhalf3 Diffuse; +}; + +uniform DynamicLight u_DynamicLights[NUM_DLIGHTS]; +uniform int u_NumDynamicLights; +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#define DLIGHTS_SURFACE_NORMAL_IN +#ifdef DLIGHTS_SURFACE_NORMAL_IN +myhalf3 DynamicLightsSummaryColor(in vec3 Position, in myhalf3 surfaceNormalModelspace) +#else +myhalf3 DynamicLightsSummaryColor(in vec3 Position) +#endif +{ + myhalf3 Color = myhalf3(0.0); + +#if QF_GLSL_VERSION >= 330 + for (int i = 0; i < u_NumDynamicLights; i++) +#else + for (int i = 0; i < NUM_DLIGHTS; i++) +#endif + { + myhalf3 STR = myhalf3(u_DynamicLights[i].Position - Position); + myhalf distance = length(STR); + myhalf falloff = clamp(1.0 - distance / u_DynamicLights[i].Radius, 0.0, 1.0); + + falloff *= falloff; + + #ifdef DLIGHTS_SURFACE_NORMAL_IN + falloff *= myhalf(max(dot(normalize(STR), surfaceNormalModelspace), 0.0)); + #endif + + Color += falloff * u_DynamicLights[i].Diffuse; + } + + return Color; +} + + +#endif + +#endif +#endif + +#ifdef APPLY_FOG +struct Fog +{ + float EyeDist; + vec4 EyePlane, Plane; + myhalf3 Color; + float Scale; +}; + +uniform Fog u_Fog; + +#define FOG_TEXCOORD_STEP 1.0/256.0 + +#define FogDensity(coord) sqrt(clamp((coord)[0],0.0,1.0))*step(FOG_TEXCOORD_STEP,(coord)[1]) + +#define FOG_GEN_OUTPUT_COLOR +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + + +#undef FOG_GEN_OUTPUT_COLOR +#define FOG_GEN_OUTPUT_TEXCOORDS +#if defined(FOG_GEN_OUTPUT_COLOR) +void FogGen(in vec4 Position, inout myhalf4 outColor, in myhalf2 blendMix) +#elif defined(FOG_GEN_OUTPUT_TEXCOORDS) +void FogGen(in vec4 Position, inout vec2 outTexCoord) +#endif +{ + // side = vec2(inside, outside) + myhalf2 side = myhalf2(step(u_Fog.EyeDist, 0.0), step(0.0, u_Fog.EyeDist)); + myhalf FDist = dot(Position.xyz, u_Fog.EyePlane.xyz) - u_Fog.EyePlane.w; + myhalf FVdist = dot(Position.xyz, u_Fog.Plane.xyz) - u_Fog.Plane.w; + myhalf FogDistScale = FVdist / (FVdist - u_Fog.EyeDist); + +#if defined(FOG_GEN_OUTPUT_COLOR) + myhalf FogDist = FDist * dot(side, myhalf2(1.0, FogDistScale)); + myhalf FogScale = myhalf(clamp(1.0 - FogDist * u_Fog.Scale, 0.0, 1.0)); + outColor *= mix(myhalf4(1.0), myhalf4(FogScale), blendMix.xxxy); +#endif + +#if defined(FOG_GEN_OUTPUT_TEXCOORDS) + myhalf FogS = FDist * dot(side, myhalf2(1.0, step(FVdist, 0.0) * FogDistScale)); + myhalf FogT = -FVdist; + outTexCoord = vec2(FogS * u_Fog.Scale, FogT * u_Fog.Scale + 1.5*FOG_TEXCOORD_STEP); +#endif +} + +#endif +#ifdef APPLY_GREYSCALE +myhalf3 Greyscale(myhalf3 color) +{ + return myhalf3(dot(color, myhalf3(0.299, 0.587, 0.114))); +} + +#endif + +qf_varying vec2 v_TexCoord; +#ifdef NUM_LIGHTMAPS +qf_varying vec2 v_LightmapTexCoord[NUM_LIGHTMAPS]; +#endif + +qf_varying vec3 v_Position; + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +qf_varying vec3 v_EyeVector; +#endif + +qf_varying mat3 v_StrMatrix; // directions of S/T/R texcoords (tangent, binormal, normal) + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) +qf_varying vec2 v_FogCoord; +#endif + +#ifdef VERTEX_SHADER +#ifdef VERTEX_SHADER +qf_attribute vec4 a_Position; +qf_attribute vec4 a_SVector; +qf_attribute vec4 a_Normal; +qf_attribute vec4 a_Color; +qf_attribute vec2 a_TexCoord; +qf_attribute vec2 a_LightmapCoord0, a_LightmapCoord1, a_LightmapCoord2, a_LightmapCoord3; +#endif +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} + +void TransformVerts(inout vec4 Position, inout vec3 Normal, inout vec3 Tangent, inout vec2 TexCoord) +{ +#ifdef NUM_BONE_INFLUENCES + QF_VertexDualQuatsTransform(NUM_BONE_INFLUENCES, Position, Normal, Tangent); +#endif + +#ifdef APPLY_DEFORMVERTS + QF_DeformVerts(Position, Normal, TexCoord); +#endif + +#ifdef APPLY_INSTANCED_TRANSFORMS + QF_InstancedTransform(Position, Normal); +#endif +} +myhalf4 VertexRGBGen(in vec4 Position, in vec3 Normal, in myhalf4 VertexColor) +{ +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#define DISTANCERAMP(x1,x2,y1,y2) ((y2 - y1) / (x2 - x1) * (clamp(myhalf(dot(u_EntityDist - Position.xyz, Normal)),0.0,x2) - x1) + y1) +#endif + +#if defined(APPLY_RGB_CONST) && defined(APPLY_ALPHA_CONST) + myhalf4 Color = u_ConstColor; +#else + myhalf4 Color = myhalf4(1.0); + +#if defined(APPLY_RGB_CONST) + Color.rgb = u_ConstColor.rgb; +#elif defined(APPLY_RGB_VERTEX) + Color.rgb = VertexColor.rgb; +#elif defined(APPLY_RGB_ONE_MINUS_VERTEX) + Color.rgb = myhalf3(1.0) - VertexColor.rgb; +#elif defined(APPLY_RGB_GEN_DIFFUSELIGHT) + Color.rgb = myhalf3(u_LightAmbient + max(dot(u_LightDir, Normal), 0.0) * u_LightDiffuse); +#endif + +#if defined(APPLY_ALPHA_CONST) + Color.a = u_ConstColor.a; +#elif defined(APPLY_ALPHA_VERTEX) + Color.a = VertexColor.a; +#elif defined(APPLY_ALPHA_ONE_MINUS_VERTEX) + Color.a = 1.0 - VertexColor.a; +#endif + +#endif + +#ifdef APPLY_RGB_DISTANCERAMP + Color.rgb *= DISTANCERAMP(u_RGBGenFuncArgs[2], u_RGBGenFuncArgs[3], u_RGBGenFuncArgs[0], u_RGBGenFuncArgs[1]); +#endif + +#ifdef APPLY_ALPHA_DISTANCERAMP + Color.a *= DISTANCERAMP(u_AlphaGenFuncArgs[2], u_AlphaGenFuncArgs[3], u_AlphaGenFuncArgs[0], u_AlphaGenFuncArgs[1]); +#endif + + return Color; +#if defined(APPLY_RGB_DISTANCERAMP) || defined(APPLY_ALPHA_DISTANCERAMP) +#undef DISTANCERAMP +#endif +} + + +void main() +{ + vec4 Position = a_Position; + vec3 Normal = a_Normal.xyz; + myhalf4 inColor = myhalf4(a_Color); + vec2 TexCoord = a_TexCoord; + vec3 Tangent = a_SVector.xyz; + float TangentDir = a_SVector.w; + + TransformVerts(Position, Normal, Tangent, TexCoord); + + myhalf4 outColor = VertexRGBGen(Position, Normal, inColor); + +#ifdef APPLY_FOG +#if defined(APPLY_FOG_COLOR) + FogGen(Position, outColor, u_BlendMix); +#else + FogGen(Position, v_FogCoord); +#endif +#endif // APPLY_FOG + + qf_FrontColor = vec4(outColor); + + v_TexCoord = TextureMatrix2x3Mul(u_TextureMatrix, TexCoord); + +#ifdef NUM_LIGHTMAPS + v_LightmapTexCoord[0] = a_LightmapCoord0; +#if NUM_LIGHTMAPS >= 2 + v_LightmapTexCoord[1] = a_LightmapCoord1; +#if NUM_LIGHTMAPS >= 3 + v_LightmapTexCoord[2] = a_LightmapCoord2; +#if NUM_LIGHTMAPS >= 4 + v_LightmapTexCoord[3] = a_LightmapCoord3; +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + + v_StrMatrix[0] = Tangent; + v_StrMatrix[2] = Normal; + v_StrMatrix[1] = TangentDir * cross(Normal, Tangent); + +#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + vec3 EyeVectorWorld = u_ViewOrigin - Position.xyz; + v_EyeVector = EyeVectorWorld * v_StrMatrix; +#endif + + v_Position = Position.xyz; + gl_Position = u_ModelViewProjectionMatrix * Position; +} + +#endif // VERTEX_SHADER + +#ifdef FRAGMENT_SHADER +// Fragment shader + +#ifdef NUM_LIGHTMAPS +uniform float u_DeluxemapOffset[NUM_LIGHTMAPS]; // s-offset for v_LightmapTexCoord +uniform sampler2D u_LightmapTexture[NUM_LIGHTMAPS]; +#endif + +uniform sampler2D u_BaseTexture; +uniform sampler2D u_NormalmapTexture; +uniform sampler2D u_GlossTexture; +#ifdef APPLY_DECAL +uniform sampler2D u_DecalTexture; +#endif + +#ifdef APPLY_ENTITY_DECAL +uniform sampler2D u_EntityDecalTexture; +#endif + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +uniform float u_OffsetMappingScale; +#endif + +#ifdef APPLY_DRAWFLAT +uniform myhalf3 u_WallColor; +uniform myhalf3 u_FloorColor; +#endif + +uniform myhalf u_GlossIntensity; // gloss scaling factor +uniform myhalf u_GlossExponent; // gloss exponent factor + +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) +// The following reliefmapping and offsetmapping routine was taken from DarkPlaces +// The credit goes to LordHavoc (as always) +vec2 OffsetMapping(vec2 TexCoord) +{ +#ifdef APPLY_RELIEFMAPPING + // 14 sample relief mapping: linear search and then binary search + // this basically steps forward a small amount repeatedly until it finds + // itself inside solid, then jitters forward and back using decreasing + // amounts to find the impact + //vec3 OffsetVector = vec3(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1), -1); + //vec3 OffsetVector = vec3(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 OffsetVector = vec3(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1), -1); + vec3 RT = vec3(TexCoord, 1); + OffsetVector *= 0.1; + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) - 0.5); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625); + RT += OffsetVector * (step(qf_texture(u_NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125); + return RT.xy; +#else + // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits) + // this basically moves forward the full distance, and then backs up based + // on height of samples + //vec2 OffsetVector = vec2(v_EyeVector.xy * ((1.0 / v_EyeVector.z) * u_OffsetMappingScale) * vec2(-1, 1)); + //vec2 OffsetVector = vec2(normalize(v_EyeVector.xy) * u_OffsetMappingScale * vec2(-1, 1)); + vec2 OffsetVector = vec2(normalize(v_EyeVector).xy * u_OffsetMappingScale * vec2(-1, 1)); + TexCoord += OffsetVector; + OffsetVector *= 0.5; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + TexCoord -= OffsetVector * qf_texture(u_NormalmapTexture, TexCoord).a; + return TexCoord; +#endif // APPLY_RELIEFMAPPING +} +#endif // defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + +void main() +{ +#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING) + // apply offsetmapping + vec2 TexCoordOffset = OffsetMapping(v_TexCoord); +#define v_TexCoord TexCoordOffset +#endif + + myhalf3 surfaceNormal; + myhalf3 surfaceNormalModelspace; + myhalf3 diffuseNormalModelspace; + float diffuseProduct; + +#ifdef APPLY_CELSHADING + int lightcell; + float diffuseProductPositive; + float diffuseProductNegative; + float hardShadow; +#endif + + myhalf3 weightedDiffuseNormalModelspace; + +#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(NUM_LIGHTMAPS) + myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0); +#else + myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0); +#endif + + myhalf4 decal = myhalf4 (0.0, 0.0, 0.0, 1.0); + + // get the surface normal + surfaceNormal = normalize(myhalf3(qf_texture (u_NormalmapTexture, v_TexCoord)) - myhalf3 (0.5)); + surfaceNormalModelspace = normalize(v_StrMatrix * surfaceNormal); + +#ifdef APPLY_DIRECTIONAL_LIGHT + +#ifdef APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + diffuseNormalModelspace = v_StrMatrix[2]; +#else + diffuseNormalModelspace = u_LightDir; +#endif // APPLY_DIRECTIONAL_LIGHT_FROM_NORMAL + + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + +#ifdef APPLY_CELSHADING + hardShadow = 0.0; +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = float ( clamp(diffuseProduct, 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProductPositive *= diffuseProductPositive; + diffuseProductNegative = float ( clamp(diffuseProduct, -1.0, 0.0) * 0.5 - 0.5 ); + diffuseProductNegative *= diffuseProductNegative; + diffuseProductNegative -= 0.25; + diffuseProduct = diffuseProductPositive; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + diffuseProductPositive = max (diffuseProduct, 0.0); + diffuseProductNegative = (-min (diffuseProduct, 0.0) - 0.3); +#endif // APPLY_HALFLAMBERT + + // smooth the hard shadow edge + lightcell = int(max(diffuseProduct + 0.1, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(max(diffuseProduct + 0.055, 0.0) * 2.0); + hardShadow += float(lightcell); + + lightcell = int(diffuseProductPositive * 2.0); + hardShadow += float(lightcell); + + color.rgb += myhalf(0.6 + hardShadow * 0.3333333333 * 0.27 + diffuseProductPositive * 0.14); + + // backlight + lightcell = int (diffuseProductNegative * 2.0); + color.rgb += myhalf (float(lightcell) * 0.085 + diffuseProductNegative * 0.085); +#else + +#ifdef APPLY_HALFLAMBERT + diffuseProduct = float ( clamp(dot (surfaceNormalModelspace, diffuseNormalModelspace), 0.0, 1.0) * 0.5 + 0.5 ); + diffuseProduct *= diffuseProduct; +#else + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); +#endif // APPLY_HALFLAMBERT + +#ifdef APPLY_DIRECTIONAL_LIGHT_MIX + color.rgb += qf_FrontColor.rgb; +#else + color.rgb += u_LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + u_LightAmbient; +#endif + +#endif // APPLY_CELSHADING + +#endif // APPLY_DIRECTIONAL_LIGHT + + // deluxemapping using light vectors in modelspace + +#ifdef NUM_LIGHTMAPS + // get light normal + diffuseNormalModelspace = normalize(myhalf3 (qf_texture(u_LightmapTexture[0], vec2(v_LightmapTexCoord[0].s+u_DeluxemapOffset[0],v_LightmapTexCoord[0].t))) - myhalf3 (0.5)); + // calculate directional shading + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + +#ifdef APPLY_FBLIGHTMAP + weightedDiffuseNormalModelspace = diffuseNormalModelspace; + // apply lightmap color + color.rgb += myhalf3 (max (diffuseProduct, 0.0) * myhalf3 (qf_texture (u_LightmapTexture[0], v_LightmapTexCoord[0]))); +#else +#define NORMALIZE_DIFFUSE_NORMAL + weightedDiffuseNormalModelspace = u_LightstyleColor[0] * diffuseNormalModelspace; + // apply lightmap color + color.rgb += u_LightstyleColor[0] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[0], v_LightmapTexCoord[0])); +#endif // APPLY_FBLIGHTMAP + +#ifdef APPLY_AMBIENT_COMPENSATION + // compensate for ambient lighting + color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * u_LightAmbient; +#endif + +#if NUM_LIGHTMAPS >= 2 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[1], vec2(v_LightmapTexCoord[1].s+u_DeluxemapOffset[1],v_LightmapTexCoord[1].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[1] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[1] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[1], v_LightmapTexCoord[1])); +#if NUM_LIGHTMAPS >= 3 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[2], vec2(v_LightmapTexCoord[2].s+u_DeluxemapOffset[2],v_LightmapTexCoord[2].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[2] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[2] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[2], v_LightmapTexCoord[2])); +#if NUM_LIGHTMAPS >= 4 + diffuseNormalModelspace = normalize(myhalf3 (qf_texture (u_LightmapTexture[3], vec2(v_LightmapTexCoord[3].s+u_DeluxemapOffset[3],v_LightmapTexCoord[3].t))) - myhalf3 (0.5)); + diffuseProduct = float (dot (surfaceNormalModelspace, diffuseNormalModelspace)); + weightedDiffuseNormalModelspace += u_LightstyleColor[3] * diffuseNormalModelspace; + color.rgb += u_LightstyleColor[3] * myhalf(max (diffuseProduct, 0.0)) * myhalf3 (qf_texture(u_LightmapTexture[3], v_LightmapTexCoord[3])); +#endif // NUM_LIGHTMAPS >= 4 +#endif // NUM_LIGHTMAPS >= 3 +#endif // NUM_LIGHTMAPS >= 2 +#endif // NUM_LIGHTMAPS + +#if defined(NUM_DLIGHTS) + color.rgb += DynamicLightsSummaryColor(v_Position, surfaceNormalModelspace); +#endif + +#ifdef APPLY_SPECULAR + +#ifdef NORMALIZE_DIFFUSE_NORMAL + myhalf3 specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormalModelspace)) + myhalf3 (normalize (u_EntityDist - v_Position))); +#else + myhalf3 specularNormal = normalize (weightedDiffuseNormalModelspace + myhalf3 (normalize (u_EntityDist - v_Position))); +#endif + + myhalf specularProduct = myhalf(dot (surfaceNormalModelspace, specularNormal)); + color.rgb += (myhalf3(qf_texture(u_GlossTexture, v_TexCoord)) * u_GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), u_GlossExponent); +#endif // APPLY_SPECULAR + +#if defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + color = min(color, myhalf4(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + myhalf4 diffuse; + +#ifdef APPLY_DRAWFLAT + myhalf n = myhalf(step(DRAWFLAT_NORMAL_STEP, abs(v_StrMatrix[2].z))); + diffuse = myhalf4(mix(u_WallColor, u_FloorColor, n), myhalf(qf_texture(u_BaseTexture, v_TexCoord).a)); +#else + diffuse = myhalf4(qf_texture(u_BaseTexture, v_TexCoord)); +#endif + +#ifdef APPLY_ENTITY_DECAL + +#ifdef APPLY_ENTITY_DECAL_ADD + decal.rgb = myhalf3(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb += u_EntityColor.rgb * decal.rgb; +#else + decal = myhalf4(u_EntityColor.rgb, 1.0) * myhalf4(qf_texture(u_EntityDecalTexture, v_TexCoord)); + diffuse.rgb = mix(diffuse.rgb, decal.rgb, decal.a); +#endif // APPLY_ENTITY_DECAL_ADD + +#endif // APPLY_ENTITY_DECAL + +color = color * diffuse; +#endif // defined(APPLY_BASETEX_ALPHA_ONLY) && !defined(APPLY_DRAWFLAT) + +#ifdef APPLY_DECAL + +#ifdef APPLY_DECAL_ADD + decal.rgb = myhalf3(qf_FrontColor.rgb) * myhalf3(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = decal.rgb + color.rgb; + color.a = color.a * myhalf(qf_FrontColor.a); +#else + decal = myhalf4(qf_FrontColor) * myhalf4(qf_texture(u_DecalTexture, v_TexCoord)); + color.rgb = mix(color.rgb, decal.rgb, decal.a); +#endif // APPLY_DECAL_ADD + +#else + +#if defined (APPLY_DIRECTIONAL_LIGHT) && defined(APPLY_DIRECTIONAL_LIGHT_MIX) + color = color; +#else + color = color * myhalf4(qf_FrontColor); +#endif + +#endif // APPLY_DECAL + +#ifdef APPLY_GREYSCALE + color.rgb = Greyscale(color.rgb); +#endif + +#if defined(APPLY_FOG) && !defined(APPLY_FOG_COLOR) + myhalf fogDensity = FogDensity(v_FogCoord); + color.rgb = mix(color.rgb, u_Fog.Color, fogDensity); +#endif + + qf_FragColor = vec4(color); +} + +#endif // FRAGMENT_SHADER + -- cgit v1.2.3