summaryrefslogtreecommitdiff
path: root/src/renderergl2/glsl/lightall_fp.glsl
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderergl2/glsl/lightall_fp.glsl')
-rw-r--r--src/renderergl2/glsl/lightall_fp.glsl429
1 files changed, 429 insertions, 0 deletions
diff --git a/src/renderergl2/glsl/lightall_fp.glsl b/src/renderergl2/glsl/lightall_fp.glsl
new file mode 100644
index 0000000..8e7c9b4
--- /dev/null
+++ b/src/renderergl2/glsl/lightall_fp.glsl
@@ -0,0 +1,429 @@
+uniform sampler2D u_DiffuseMap;
+
+#if defined(USE_LIGHTMAP)
+uniform sampler2D u_LightMap;
+#endif
+
+#if defined(USE_NORMALMAP)
+uniform sampler2D u_NormalMap;
+#endif
+
+#if defined(USE_DELUXEMAP)
+uniform sampler2D u_DeluxeMap;
+#endif
+
+#if defined(USE_SPECULARMAP)
+uniform sampler2D u_SpecularMap;
+#endif
+
+#if defined(USE_SHADOWMAP)
+uniform sampler2D u_ShadowMap;
+#endif
+
+#if defined(USE_CUBEMAP)
+uniform samplerCube u_CubeMap;
+#endif
+
+#if defined(USE_NORMALMAP) || defined(USE_DELUXEMAP) || defined(USE_SPECULARMAP) || defined(USE_CUBEMAP)
+// y = deluxe, w = cube
+uniform vec4 u_EnableTextures;
+#endif
+
+#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
+uniform vec3 u_PrimaryLightColor;
+uniform vec3 u_PrimaryLightAmbient;
+#endif
+
+#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
+uniform vec4 u_NormalScale;
+uniform vec4 u_SpecularScale;
+#endif
+
+#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
+#if defined(USE_CUBEMAP)
+uniform vec4 u_CubeMapInfo;
+#endif
+#endif
+
+uniform int u_AlphaTest;
+
+varying vec4 var_TexCoords;
+
+varying vec4 var_Color;
+#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT))
+varying vec4 var_ColorAmbient;
+#endif
+
+#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT))
+varying vec4 var_Normal;
+varying vec4 var_Tangent;
+varying vec4 var_Bitangent;
+#endif
+
+#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
+varying vec4 var_LightDir;
+#endif
+
+#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
+varying vec4 var_PrimaryLightDir;
+#endif
+
+
+#define EPSILON 0.00000001
+
+#if defined(USE_PARALLAXMAP)
+float SampleDepth(sampler2D normalMap, vec2 t)
+{
+ #if defined(SWIZZLE_NORMALMAP)
+ return 1.0 - texture2D(normalMap, t).r;
+ #else
+ return 1.0 - texture2D(normalMap, t).a;
+ #endif
+}
+
+float RayIntersectDisplaceMap(vec2 dp, vec2 ds, sampler2D normalMap)
+{
+ const int linearSearchSteps = 16;
+ const int binarySearchSteps = 6;
+
+ // current size of search window
+ float size = 1.0 / float(linearSearchSteps);
+
+ // current depth position
+ float depth = 0.0;
+
+ // best match found (starts with last position 1.0)
+ float bestDepth = 1.0;
+
+ // texture depth at best depth
+ float texDepth = 0.0;
+
+ float prevT = SampleDepth(normalMap, dp);
+ float prevTexDepth = prevT;
+
+ // search front to back for first point inside object
+ for(int i = 0; i < linearSearchSteps - 1; ++i)
+ {
+ depth += size;
+
+ float t = SampleDepth(normalMap, dp + ds * depth);
+
+ if(bestDepth > 0.996) // if no depth found yet
+ if(depth >= t)
+ {
+ bestDepth = depth; // store best depth
+ texDepth = t;
+ prevTexDepth = prevT;
+ }
+ prevT = t;
+ }
+
+ depth = bestDepth;
+
+#if !defined (USE_RELIEFMAP)
+ float div = 1.0 / (1.0 + (prevTexDepth - texDepth) * float(linearSearchSteps));
+ bestDepth -= (depth - size - prevTexDepth) * div;
+#else
+ // recurse around first point (depth) for closest match
+ for(int i = 0; i < binarySearchSteps; ++i)
+ {
+ size *= 0.5;
+
+ float t = SampleDepth(normalMap, dp + ds * depth);
+
+ if(depth >= t)
+ {
+ bestDepth = depth;
+ depth -= 2.0 * size;
+ }
+
+ depth += size;
+ }
+#endif
+
+ return bestDepth;
+}
+#endif
+
+vec3 CalcDiffuse(vec3 diffuseAlbedo, float NH, float EH, float roughness)
+{
+#if defined(USE_BURLEY)
+ // modified from https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf
+ float fd90 = -0.5 + EH * EH * roughness;
+ float burley = 1.0 + fd90 * 0.04 / NH;
+ burley *= burley;
+ return diffuseAlbedo * burley;
+#else
+ return diffuseAlbedo;
+#endif
+}
+
+vec3 EnvironmentBRDF(float roughness, float NE, vec3 specular)
+{
+ // from http://community.arm.com/servlet/JiveServlet/download/96891546-19496/siggraph2015-mmg-renaldas-slides.pdf
+ float v = 1.0 - max(roughness, NE);
+ v *= v * v;
+ return vec3(v) + specular;
+}
+
+vec3 CalcSpecular(vec3 specular, float NH, float EH, float roughness)
+{
+ // from http://community.arm.com/servlet/JiveServlet/download/96891546-19496/siggraph2015-mmg-renaldas-slides.pdf
+ float rr = roughness*roughness;
+ float rrrr = rr*rr;
+ float d = (NH * NH) * (rrrr - 1.0) + 1.0;
+ float v = (EH * EH) * (roughness + 0.5);
+ return specular * (rrrr / (4.0 * d * d * v));
+}
+
+
+float CalcLightAttenuation(float point, float normDist)
+{
+ // zero light at 1.0, approximating q3 style
+ // also don't attenuate directional light
+ float attenuation = (0.5 * normDist - 1.5) * point + 1.0;
+
+ // clamp attenuation
+ #if defined(NO_LIGHT_CLAMP)
+ attenuation = max(attenuation, 0.0);
+ #else
+ attenuation = clamp(attenuation, 0.0, 1.0);
+ #endif
+
+ return attenuation;
+}
+
+
+void main()
+{
+ vec3 viewDir, lightColor, ambientColor, reflectance;
+ vec3 L, N, E, H;
+ float NL, NH, NE, EH, attenuation;
+
+#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
+ mat3 tangentToWorld = mat3(var_Tangent.xyz, var_Bitangent.xyz, var_Normal.xyz);
+ viewDir = vec3(var_Normal.w, var_Tangent.w, var_Bitangent.w);
+ E = normalize(viewDir);
+#endif
+
+ lightColor = var_Color.rgb;
+
+#if defined(USE_LIGHTMAP)
+ vec4 lightmapColor = texture2D(u_LightMap, var_TexCoords.zw);
+ #if defined(RGBM_LIGHTMAP)
+ lightmapColor.rgb *= lightmapColor.a;
+ #endif
+ #if defined(USE_PBR) && !defined(USE_FAST_LIGHT)
+ lightmapColor.rgb *= lightmapColor.rgb;
+ #endif
+ lightColor *= lightmapColor.rgb;
+#endif
+
+ vec2 texCoords = var_TexCoords.xy;
+
+#if defined(USE_PARALLAXMAP)
+ vec3 offsetDir = viewDir * tangentToWorld;
+
+ offsetDir.xy *= -u_NormalScale.a / offsetDir.z;
+
+ texCoords += offsetDir.xy * RayIntersectDisplaceMap(texCoords, offsetDir.xy, u_NormalMap);
+#endif
+
+ vec4 diffuse = texture2D(u_DiffuseMap, texCoords);
+
+ float alpha = diffuse.a * var_Color.a;
+ if (u_AlphaTest == 1)
+ {
+ if (alpha == 0.0)
+ discard;
+ }
+ else if (u_AlphaTest == 2)
+ {
+ if (alpha >= 0.5)
+ discard;
+ }
+ else if (u_AlphaTest == 3)
+ {
+ if (alpha < 0.5)
+ discard;
+ }
+
+#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
+ L = var_LightDir.xyz;
+ #if defined(USE_DELUXEMAP)
+ L += (texture2D(u_DeluxeMap, var_TexCoords.zw).xyz - vec3(0.5)) * u_EnableTextures.y;
+ #endif
+ float sqrLightDist = dot(L, L);
+ L /= sqrt(sqrLightDist);
+
+ #if defined(USE_LIGHT_VECTOR)
+ attenuation = CalcLightAttenuation(float(var_LightDir.w > 0.0), var_LightDir.w / sqrLightDist);
+ #else
+ attenuation = 1.0;
+ #endif
+
+ #if defined(USE_NORMALMAP)
+ #if defined(SWIZZLE_NORMALMAP)
+ N.xy = texture2D(u_NormalMap, texCoords).ag - vec2(0.5);
+ #else
+ N.xy = texture2D(u_NormalMap, texCoords).rg - vec2(0.5);
+ #endif
+ N.xy *= u_NormalScale.xy;
+ N.z = sqrt(clamp((0.25 - N.x * N.x) - N.y * N.y, 0.0, 1.0));
+ N = tangentToWorld * N;
+ #else
+ N = var_Normal.xyz;
+ #endif
+
+ N = normalize(N);
+
+ #if defined(USE_SHADOWMAP)
+ vec2 shadowTex = gl_FragCoord.xy * r_FBufScale;
+ float shadowValue = texture2D(u_ShadowMap, shadowTex).r;
+
+ // surfaces not facing the light are always shadowed
+ shadowValue *= clamp(dot(N, var_PrimaryLightDir.xyz), 0.0, 1.0);
+
+ #if defined(SHADOWMAP_MODULATE)
+ lightColor *= shadowValue * (1.0 - u_PrimaryLightAmbient.r) + u_PrimaryLightAmbient.r;
+ #endif
+ #endif
+
+ #if !defined(USE_LIGHT_VECTOR)
+ ambientColor = lightColor;
+ float surfNL = clamp(dot(var_Normal.xyz, L), 0.0, 1.0);
+
+ // reserve 25% ambient to avoid black areas on normalmaps
+ lightColor *= 0.75;
+
+ // Scale the incoming light to compensate for the baked-in light angle
+ // attenuation.
+ lightColor /= max(surfNL, 0.25);
+
+ // Recover any unused light as ambient, in case attenuation is over 4x or
+ // light is below the surface
+ ambientColor = max(ambientColor - lightColor * surfNL, vec3(0.0));
+ #else
+ ambientColor = var_ColorAmbient.rgb;
+ #endif
+
+ NL = clamp(dot(N, L), 0.0, 1.0);
+ NE = clamp(dot(N, E), 0.0, 1.0);
+
+ #if defined(USE_SPECULARMAP)
+ vec4 specular = texture2D(u_SpecularMap, texCoords);
+ #else
+ vec4 specular = vec4(1.0);
+ #endif
+ specular *= u_SpecularScale;
+
+ #if defined(USE_PBR)
+ diffuse.rgb *= diffuse.rgb;
+ #endif
+
+ #if defined(USE_PBR)
+ // diffuse rgb is base color
+ // specular red is gloss
+ // specular green is metallicness
+ float gloss = specular.r;
+ float metal = specular.g;
+ specular.rgb = metal * diffuse.rgb + vec3(0.04 - 0.04 * metal);
+ diffuse.rgb *= 1.0 - metal;
+ #else
+ // diffuse rgb is diffuse
+ // specular rgb is specular reflectance at normal incidence
+ // specular alpha is gloss
+ float gloss = specular.a;
+
+ // adjust diffuse by specular reflectance, to maintain energy conservation
+ diffuse.rgb *= vec3(1.0) - specular.rgb;
+ #endif
+
+ #if defined(GLOSS_IS_GLOSS)
+ float roughness = exp2(-3.0 * gloss);
+ #elif defined(GLOSS_IS_SMOOTHNESS)
+ float roughness = 1.0 - gloss;
+ #elif defined(GLOSS_IS_ROUGHNESS)
+ float roughness = gloss;
+ #elif defined(GLOSS_IS_SHININESS)
+ float roughness = pow(2.0 / (8190.0 * gloss + 2.0), 0.25);
+ #endif
+
+ reflectance = CalcDiffuse(diffuse.rgb, NH, EH, roughness);
+
+ gl_FragColor.rgb = lightColor * reflectance * (attenuation * NL);
+ gl_FragColor.rgb += ambientColor * diffuse.rgb;
+
+ #if defined(USE_CUBEMAP)
+ reflectance = EnvironmentBRDF(roughness, NE, specular.rgb);
+
+ vec3 R = reflect(E, N);
+
+ // parallax corrected cubemap (cheaper trick)
+ // from http://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
+ vec3 parallax = u_CubeMapInfo.xyz + u_CubeMapInfo.w * viewDir;
+
+ vec3 cubeLightColor = textureCubeLod(u_CubeMap, R + parallax, ROUGHNESS_MIPS * roughness).rgb * u_EnableTextures.w;
+
+ // normalize cubemap based on last roughness mip (~diffuse)
+ // multiplying cubemap values by lighting below depends on either this or the cubemap being normalized at generation
+ //vec3 cubeLightDiffuse = max(textureCubeLod(u_CubeMap, N, ROUGHNESS_MIPS).rgb, 0.5 / 255.0);
+ //cubeLightColor /= dot(cubeLightDiffuse, vec3(0.2125, 0.7154, 0.0721));
+
+ #if defined(USE_PBR)
+ cubeLightColor *= cubeLightColor;
+ #endif
+
+ // multiply cubemap values by lighting
+ // not technically correct, but helps make reflections look less unnatural
+ //cubeLightColor *= lightColor * (attenuation * NL) + ambientColor;
+
+ gl_FragColor.rgb += cubeLightColor * reflectance;
+ #endif
+
+ #if defined(USE_PRIMARY_LIGHT) || defined(SHADOWMAP_MODULATE)
+ vec3 L2, H2;
+ float NL2, EH2, NH2;
+
+ L2 = var_PrimaryLightDir.xyz;
+
+ // enable when point lights are supported as primary lights
+ //sqrLightDist = dot(L2, L2);
+ //L2 /= sqrt(sqrLightDist);
+
+ NL2 = clamp(dot(N, L2), 0.0, 1.0);
+ H2 = normalize(L2 + E);
+ EH2 = clamp(dot(E, H2), 0.0, 1.0);
+ NH2 = clamp(dot(N, H2), 0.0, 1.0);
+
+ reflectance = CalcSpecular(specular.rgb, NH2, EH2, roughness);
+
+ // bit of a hack, with modulated shadowmaps, ignore diffuse
+ #if !defined(SHADOWMAP_MODULATE)
+ reflectance += CalcDiffuse(diffuse.rgb, NH2, EH2, roughness);
+ #endif
+
+ lightColor = u_PrimaryLightColor;
+
+ #if defined(USE_SHADOWMAP)
+ lightColor *= shadowValue;
+ #endif
+
+ // enable when point lights are supported as primary lights
+ //lightColor *= CalcLightAttenuation(float(u_PrimaryLightDir.w > 0.0), u_PrimaryLightDir.w / sqrLightDist);
+
+ gl_FragColor.rgb += lightColor * reflectance * NL2;
+ #endif
+
+ #if defined(USE_PBR)
+ gl_FragColor.rgb = sqrt(gl_FragColor.rgb);
+ #endif
+
+#else
+
+ gl_FragColor.rgb = diffuse.rgb * lightColor;
+
+#endif
+
+ gl_FragColor.a = alpha;
+}