1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
|
#version 410 core
// #define use_normalmapping
// #define flip_normalmap
const float DEGREES_TO_RADIANS = 3.141592653589793 / 180.0;
uniform sampler2D diffuseTex;
uniform sampler2D shadingTex;
uniform samplerCube reflectTex;
#ifdef use_normalmapping
uniform sampler2D normalMap;
#endif
uniform vec3 sunDir;
uniform vec3 sunDiffuse; // model
uniform vec3 sunAmbient; // model
uniform vec3 sunSpecular; // model
#if (USE_SHADOWS == 1)
uniform sampler2DShadow shadowTex;
uniform mat4 shadowMatrix;
uniform vec4 shadowParams;
uniform float shadowDensity;
#endif
uniform float specularExponent;
uniform float gammaExponent;
uniform vec4 fogColor;
// in opaque passes tc.a is always 1.0 [all objects], and alphaPass is 0.0
// in alpha passes tc.a is either one of alphaValues.xyzw [for units] *or*
// contains a distance fading factor [for features], and alphaPass is 1.0
// texture alpha-masking is done in both passes
uniform vec4 teamColor;
uniform vec4 nanoColor;
// uniform float alphaPass;
uniform vec4 alphaTestCtrl;
// fwdDynLights[i] := {pos, dir, diffuse, specular, ambient, {fov, radius, -, -}}
uniform vec4 fwdDynLights[MAX_LIGHT_UNIFORM_VECS];
in vec4 worldPos;
in vec3 cameraDir;
in vec2 texCoord0;
// in vec2 texCoord1;
in float fogFactor;
#ifdef use_normalmapping
in mat3 tbnMatrix;
#else
in vec3 wsNormalVec;
#endif
#if (DEFERRED_MODE == 0)
layout(location = 0) out vec4 fragColor;
#else
layout(location = 0) out vec4 fragData[MDL_FRAGDATA_COUNT];
#endif
float GetShadowCoeff(float zBias) {
#if (USE_SHADOWS == 1)
vec4 vertexShadowPos = shadowMatrix * worldPos;
vertexShadowPos.z += zBias;
return mix(1.0, textureProj(shadowTex, vertexShadowPos), shadowDensity);
#endif
return 1.0;
}
vec3 DynamicLighting(vec3 wsNormal, vec3 camDir, vec3 diffuseColor, vec4 specularColor) {
vec3 light = vec3(0.0);
#if (NUM_DYNAMIC_MODEL_LIGHTS > 0)
for (int i = 0; i < NUM_DYNAMIC_MODEL_LIGHTS; i++) {
int j = i * 6;
vec4 wsLightPos = fwdDynLights[j + 0];
vec4 wsLightDir = fwdDynLights[j + 1];
vec4 lightDiffColor = fwdDynLights[j + 2];
vec4 lightSpecColor = fwdDynLights[j + 3];
vec4 lightAmbiColor = fwdDynLights[j + 4];
vec3 wsLightVec = normalize(wsLightPos.xyz - worldPos.xyz);
vec3 wsHalfVec = normalize(camDir + wsLightVec);
float lightAngle = fwdDynLights[j + 5].x; // fov
float lightRadius = fwdDynLights[j + 5].y; // or const. atten.
float lightDistance = dot(wsLightVec, wsLightPos.xyz - worldPos.xyz);
float lightCosAngleDiff = clamp(dot(wsNormal, wsLightVec), 0.0, 1.0);
float lightCosAngleSpec = clamp(dot(wsNormal, wsHalfVec), 0.001, 1.0);
#ifdef OGL_SPEC_ATTENUATION
// infinite falloff
float cLightAtten = fwdDynLights[j + 5].y;
float lLightAtten = fwdDynLights[j + 5].z;
float qLightAtten = fwdDynLights[j + 5].w;
float lightAtten = cLightAtten + lLightAtten * lightDistance + qLightAtten * lightDistance * lightDistance;
float lightConst = 1.0;
lightAtten = 1.0 / max(lightAtten, 1.0);
#else
float lightConst = float(lightDistance <= lightRadius);
float lightAtten = 1.0 - min(1.0, ((lightDistance * lightDistance) / (lightRadius * lightRadius)));
#endif
float lightSpecularPow = max(0.0, pow(lightCosAngleSpec, specularColor.a));
float vectorCosAngle = dot(-wsLightVec, wsLightDir.xyz);
float cutoffCosAngle = cos(lightAngle * DEGREES_TO_RADIANS);
lightConst *= float(vectorCosAngle >= cutoffCosAngle);
light += (lightConst * lightAmbiColor.rgb );
light += (lightConst * lightAtten * ( diffuseColor.rgb * lightDiffColor.rgb * lightCosAngleDiff));
light += (lightConst * lightAtten * (specularColor.rgb * lightSpecColor.rgb * lightSpecularPow ));
}
#endif
return light;
}
void main(void)
{
#ifdef use_normalmapping
vec2 tc = texCoord0;
#ifdef flip_normalmap
tc.t = 1.0 - tc.t;
#endif
vec3 tsNormal = normalize((texture(normalMap, tc).xyz - 0.5) * 2.0);
vec3 wsNormal = tbnMatrix * tsNormal;
#else
vec3 wsNormal = normalize(wsNormalVec);
#endif
vec3 reflectDir = reflect(cameraDir, wsNormal);
vec3 sunLightColor = max(dot(wsNormal, sunDir), 0.0) * sunDiffuse + sunAmbient;
vec4 diffuseColor = texture(diffuseTex, texCoord0);
vec4 shadingColor = texture(shadingTex, texCoord0);
vec3 specularColor = sunSpecular * pow(max(0.001, dot(wsNormal, normalize(sunDir + cameraDir * -1.0))), specularExponent);
vec3 reflectColor = texture(reflectTex, reflectDir).rgb;
float shadow = GetShadowCoeff(-0.00005);
float alpha = teamColor.a * shadingColor.a; // apply one-bit mask
#if (DEFERRED_MODE == 0)
float alphaTestGreater = float(alpha > alphaTestCtrl.x) * alphaTestCtrl.y;
float alphaTestSmaller = float(alpha < alphaTestCtrl.x) * alphaTestCtrl.z;
if ((alphaTestGreater + alphaTestSmaller + alphaTestCtrl.w) == 0.0)
discard;
#endif
specularColor *= (shadingColor.g * 4.0);
// no highlights if in shadow; decrease light to ambient level
specularColor *= shadow;
sunLightColor = mix(sunAmbient, sunLightColor, shadow);
reflectColor = mix(sunLightColor, reflectColor, shadingColor.g); // reflection
reflectColor += shadingColor.rrr; // self-illum
#if (DEFERRED_MODE == 0)
fragColor = diffuseColor;
fragColor.rgb = mix(fragColor.rgb, teamColor.rgb, fragColor.a); // teamcolor
fragColor.rgb = fragColor.rgb * reflectColor + specularColor;
#endif
#if (DEFERRED_MODE == 0)
fragColor.rgb += DynamicLighting(wsNormal, cameraDir * -1.0, diffuseColor.rgb, vec4(specularColor, 4.0));
#endif
#if (DEFERRED_MODE == 1)
fragData[GBUFFER_NORMTEX_IDX] = vec4((wsNormal + vec3(1.0, 1.0, 1.0)) * 0.5, 1.0);
fragData[GBUFFER_DIFFTEX_IDX] = vec4(mix( diffuseColor.rgb, teamColor.rgb, diffuseColor.a), alpha);
fragData[GBUFFER_DIFFTEX_IDX] = vec4(mix(fragData[GBUFFER_DIFFTEX_IDX].rgb, nanoColor.rgb, nanoColor.a), alpha);
// do not premultiply reflection, leave it to the deferred lighting pass
// fragData[GBUFFER_DIFFTEX_IDX] = vec4(mix(diffuseColor.rgb, teamColor.rgb, diffuseColor.a) * reflectColor, alpha);
// allows standard-lighting reconstruction by lazy LuaMaterials using us
fragData[GBUFFER_SPECTEX_IDX] = vec4(shadingColor.rgb, alpha);
fragData[GBUFFER_EMITTEX_IDX] = vec4(0.0, 0.0, 0.0, 0.0);
fragData[GBUFFER_MISCTEX_IDX] = vec4(0.0, 0.0, 0.0, 0.0);
#else
fragColor.rgb = mix(fogColor.rgb, fragColor.rgb, fogFactor); // fog
fragColor.rgb = mix(fragColor.rgb, nanoColor.rgb, nanoColor.a); // wireframe or polygon color
fragColor.rgb = pow(fragColor.rgb, vec3(gammaExponent));
fragColor.a = alpha;
#endif
}
|