#ifndef _LIGHT_MOBILE_GLSL_ #define _LIGHT_MOBILE_GLSL_ #include "compiled.inc" #include "std/brdf.glsl" #ifdef _ShadowMap #include "std/shadows.glsl" #endif #ifdef _Spot #include "std/light_common.glsl" #endif #ifdef _ShadowMap #ifdef _SinglePoint #ifdef _Spot uniform sampler2DShadow shadowMapSpot[1]; uniform mat4 LWVPSpot[1]; #else uniform samplerCubeShadow shadowMapPoint[1]; uniform vec2 lightProj; #endif #endif #ifdef _Clusters #ifdef _SingleAtlas //!uniform sampler2DShadow shadowMapAtlas; #endif uniform vec2 lightProj; #ifdef _ShadowMapAtlas #ifndef _SingleAtlas uniform sampler2DShadow shadowMapAtlasPoint; #endif #else uniform samplerCubeShadow shadowMapPoint[4]; #endif #ifdef _Spot #ifdef _ShadowMapAtlas #ifndef _SingleAtlas uniform sampler2DShadow shadowMapAtlasSpot; #endif #else uniform sampler2DShadow shadowMapSpot[maxLightsCluster]; #endif uniform mat4 LWVPSpotArray[maxLightsCluster]; #endif #endif #endif vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol, const vec3 albedo, const float rough, const float spec, const vec3 f0 #ifdef _ShadowMap , int index, float bias, bool receiveShadow #endif #ifdef _Spot , bool isSpot, float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right #endif #ifdef _ClearCoat , float clearcoat, float clearcoatRough, float coatIOR, vec3 coatTint #endif #ifdef _Sheen , float sheen, float sheenRough, vec3 sheenTint #endif #ifdef _Anisotropy , float anisotropy, float anisoRot, vec3 tangent #endif #ifdef _Subsurface , float subsurface, vec3 sssColor, vec3 sssRadius, float sssAnisotropy #endif #ifdef _Transmission , float transmission, float transRough, float ior, float thinWall #endif ) { vec3 ld = lp - p; vec3 l = normalize(ld); vec3 h = normalize(v + l); float dotNH = max(0.0, dot(n, h)); float dotVH = max(0.0, dot(v, h)); float dotNL = max(0.0, dot(n, l)); #ifdef _Anisotropy vec3 direct; if (abs(anisotropy) > 0.001) { vec3 bitangent = normalize(cross(n, tangent)); direct = lambertDiffuseBRDF(albedo, dotNL) + anisotropicBRDF(f0, rough, anisotropy, anisoRot, tangent, bitangent, n, l, v, dotNL, dotNV) * spec; } else { direct = lambertDiffuseBRDF(albedo, dotNL) + specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec; } #else vec3 direct = lambertDiffuseBRDF(albedo, dotNL) + specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec; #endif float sheenWeight = 1.0; float coatWeight = 1.0; #ifdef _Sheen vec3 sheenContrib = sheenBRDF(sheen, sheenRough, sheenTint, dotNL, dotNH, dotNV); sheenWeight = sheenAttenuation(sheen, sheenRough, sheenTint, dotNV); #endif #ifdef _ClearCoat vec3 coatContrib = clearcoatBRDF(clearcoat, clearcoatRough, coatIOR, dotNL, dotNH, dotNV, dotVH); coatWeight = coatAttenuation(clearcoat, coatIOR, dotNV); #endif float layerWeight = sheenWeight * coatWeight; direct *= layerWeight; #ifdef _Subsurface direct += subsurfaceBRDF(albedo, sssColor, sssRadius, subsurface, sssAnisotropy, dotNL) * layerWeight; #endif #ifdef _Transmission direct += transmissionBRDF(albedo, transmission, transRough, ior, thinWall, dotNL, dotNV, dotVH) * layerWeight; #endif #ifdef _ClearCoat direct *= coatTintAttenuation(clearcoat, coatTint, dotNV); direct += coatContrib * sheenWeight; #endif #ifdef _Sheen direct += sheenContrib; #endif direct *= lightCol; direct *= attenuate(distance(p, lp)); #ifdef _Spot if (isSpot) { direct *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend); #ifdef _ShadowMap if (receiveShadow) { #ifdef _SinglePoint vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0); direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias); #endif #ifdef _Clusters vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); #ifdef _ShadowMapAtlas direct *= shadowTest( #ifndef _SingleAtlas shadowMapAtlasSpot #else shadowMapAtlas #endif , lPos.xyz / lPos.w, bias ); #else if (index == 0) direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias); else if (index == 1) direct *= shadowTest(shadowMapSpot[1], lPos.xyz / lPos.w, bias); else if (index == 2) direct *= shadowTest(shadowMapSpot[2], lPos.xyz / lPos.w, bias); else if (index == 3) direct *= shadowTest(shadowMapSpot[3], lPos.xyz / lPos.w, bias); #endif #endif } #endif return direct; } #endif #ifdef _ShadowMap if (receiveShadow) { #ifdef _SinglePoint #ifndef _Spot direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n); #endif #endif #ifdef _Clusters #ifdef _ShadowMapAtlas direct *= PCFFakeCube( #ifndef _SingleAtlas shadowMapAtlasPoint #else shadowMapAtlas #endif , ld, -l, bias, lightProj, n, index ); #else if (index == 0) direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n); else if (index == 1) direct *= PCFCube(shadowMapPoint[1], ld, -l, bias, lightProj, n); else if (index == 2) direct *= PCFCube(shadowMapPoint[2], ld, -l, bias, lightProj, n); else if (index == 3) direct *= PCFCube(shadowMapPoint[3], ld, -l, bias, lightProj, n); #endif #endif } #endif return direct; } #endif