[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] #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_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