1 2// uncomment the following lines for debugging light directions: 3// yellow: light up, blue: light down, turqoise: light right, pink: light left 4// brightness: light strength 5//#define LIGHT_DEBUG 6 7// uncomment the following lines for debugging light color: 8// the light will always come from the front and have a uniform brightness. 9//#define LIGHT_DEBUG_COLOR 10 11// uncomment the following lines to set the light color to pink for all lights for debugging: 12//#define LIGHT_DEBUG_PINK 13 14#ifdef OC_DYNAMIC_LIGHT 15uniform sampler2D ambientTex; 16 17uniform mat3x2 ambientTransform; 18uniform float ambientBrightness; 19 20uniform sampler2D lightTex; 21#endif 22 23// Gamma uniforms 24uniform vec3 gamma; 25 26// 0 if backface culling is enabled, 1 if it is disabled 27uniform float cullMode; 28 29// Light dot product, taking cull mode into account 30float lightDot(vec3 normal, vec3 lightDir) { 31 return abs(max(-cullMode, dot(normalize(normal), lightDir))); 32} 33 34// Converts the pixel range 0.0..1.0 into the integer range 0..255 35int f2i(float x) { 36 return int(x * 255.9); 37} 38 39slice(init) 40{ 41 42 // At what point of light intensity we set the "darkness" point. This 43 // is to compensate for the fact that the engine "smoothes" the light 44 // and therefore will often never arrive at 0 light intensity. 45 float lightDarknessLevel = 8.0 / 256.0; 46 47 // "Height" of the light in front of the screen. The lower this 48 // value, the sharper the incoming light angles are. For 49 // orientation: A value of 1 means 45 degrees maximum. 50 float lightDepth = 0.5; 51 52 // Position of the ambient light. Note that for normal directional 53 // lights we have |X| <= 1.0 and |Y| <= 1.0, so it might be a good 54 // idea to keep within this values. 55 vec3 ambientLightPos = vec3(1.0, -1.0, lightDepth); 56 57 // Amount of ambience we put into the ambient light. The higher 58 // this is, the less directional ambient lighting is, and the 59 // "flatter" the shading appears. 60 float ambientAmbience = 1.0; 61 62 // The total brightness assigned by the ambient shader to a 63 // texture facing the viewer. 64 float maxAmbientBrightness = 1.0; 65 66 // The total brightness assigned by the ambient shader to a 67 // texture facing the viewer. 68 float maxLightBrightness = 3.0; 69 70} 71 72slice(texture+5) 73{ 74#ifdef OC_DYNAMIC_LIGHT 75 76 // Query light texture 77 vec2 lightDirCoord = lightCoord; 78 79 vec4 lightPx = texture(lightTex, lightDirCoord); 80 float lightBright = maxLightBrightness * max(0.0, (lightPx.a-lightDarknessLevel)/(1.0-lightDarknessLevel)); 81 vec3 lightDir = normalize(vec3(vec2(1.0, 1.0) - lightPx.yz * 3.0, lightDepth)); 82 83 // Query light color texture (part of the light texture) 84 vec2 lightColorCoord = lightCoord - vec2(0.0, 0.5); // subtract offset for the color texture 85 86 vec3 lightColor = texture(lightTex, lightColorCoord.st).rgb; 87 88 // Normalise light colour 89 #ifdef LIGHT_DEBUG_COLOR 90 lightBright = 0.5; 91 lightColor = vec4(1.0, 0.0, 1.0, 1.0); 92 #endif 93 94 // Ambient light 95 // Edxtra .xy since some old intel drivers return a vec3 96 float ambient = texture(ambientTex, (ambientTransform * vec3(gl_FragCoord.xy, 1.0)).xy).r; 97 ambient *= ambientBrightness; 98#ifdef OC_SKY 99 ambient = 0.999; // TODO: = 1.0 causes bugs? 100#endif 101#else 102 // When lighting is disabled, put a light source coming from the camera. 103 // Note that in most cases this does not actually matter, since in the 104 // case with lighting disabled, ambient lighting takes fully over. 105 float lightBright = 1.0; 106 vec3 lightDir = vec3(0.0, 0.0, 1.0); 107 vec3 lightColor = vec3(1.0, 1.0, 1.0); 108 float ambient = 1.0; 109#endif 110} 111 112slice(light) 113{ 114 115 // Light dot product, taking backface culling into account 116 float light = lightDot(normal, lightDir); 117 // Amount of reflection, depending on the angle where material reflects most 118 light = min(light / matAngle, 2.0 - light / matAngle); 119 120#ifdef OC_LANDSCAPE 121 normal2 = normalize(normal2); 122 float light2 = lightDot(normal2, lightDir); 123 light2 = min(light2 / matAngle2, 2.0 - light2 / matAngle2); 124#endif 125 126 // For landscape, ambient brightness is coming from top 127 vec3 ambientDir = normalize(ambientLightPos); 128 float ambientMul = maxAmbientBrightness / (ambientAmbience + lightDot(vec3(0.0,0.0,1.0), ambientDir)); 129 // Add ambience to brightness 130 lightBright = mix(lightBright, 1.0, ambient); 131 light = mix(light, ambientMul * (ambientAmbience + lightDot(normal, ambientDir)), ambient); 132#ifdef OC_LANDSCAPE 133 light2 = mix(light2, ambientMul * (ambientAmbience + lightDot(normal2, ambientDir)), ambient); 134#endif 135 lightColor = mix(lightColor, vec3(1.0,1.0,1.0), ambient); 136} 137 138slice(color+5) 139{ 140 // Normalize light colour 141 vec3 lightColorNorm = sqrt(3.0) * normalize(lightColor); 142 143 // Add light. Depending on material properties, we make it more 144 // "spotty" and allow the material to self-illuminate. The light 145 // brightness overrules everything though (= FoW is last factor). 146 vec3 spotLight = pow(vec3(light,light,light), matSpot); 147 fragColor.rgb = lightBright * fragColor.rgb * (matEmit + lightColorNorm * spotLight); 148#ifdef OC_LANDSCAPE 149 vec3 spotLight2 = pow(vec3(light2,light2,light2), matSpot2); 150 color2.rgb = lightBright * color2.rgb * (matEmit2 + lightColorNorm * spotLight2); 151#endif 152} 153 154slice(finish+5) 155{ 156 157#ifdef LIGHT_DEBUG 158#ifdef OC_DYNAMIC_LIGHT 159 float lightYDir = lightPx.b - 1.0/3.0; 160 float lightXDir = lightPx.g - 1.0/3.0; 161 float lightStrength = lightPx.a; 162 fragColor = 163 vec4(lightStrength * vec3(1.0-1.5*(max(0.0, lightYDir) + max(0.0,lightXDir)), 164 1.0-1.5*(max(0.0, lightYDir) + max(0.0,-lightXDir)), 165 1.0-1.5*max(0.0, -lightYDir)), 166 1.0); 167#else 168 fragColor = vec4(0.0, 0.0, 0.0, 0.0); // invisible 169#endif 170#endif 171 172} 173 174slice(finish+10) { 175 fragColor = vec4(pow(fragColor.rgb, gamma), fragColor.a); 176} 177