#ifndef UNITY_COMMON_LIGHTING_INCLUDED #define UNITY_COMMON_LIGHTING_INCLUDED // Ligthing convention // Light direction is oriented backward (-Z). i.e in shader code, light direction is -lightData.forward //----------------------------------------------------------------------------- // Attenuation functions //----------------------------------------------------------------------------- // Ref: Moving Frostbite to PBR float SmoothDistanceAttenuation(float squaredDistance, float invSqrAttenuationRadius) { float factor = squaredDistance * invSqrAttenuationRadius; float smoothFactor = saturate(1.0f - factor * factor); return smoothFactor * smoothFactor; } #define PUNCTUAL_LIGHT_THRESHOLD 0.01 // 1cm (in Unity 1 is 1m) float GetDistanceAttenuation(float3 unL, float invSqrAttenuationRadius) { float sqrDist = dot(unL, unL); float attenuation = 1.0f / (max(PUNCTUAL_LIGHT_THRESHOLD * PUNCTUAL_LIGHT_THRESHOLD, sqrDist)); // Non physically based hack to limit light influence to attenuationRadius. attenuation *= SmoothDistanceAttenuation(sqrDist, invSqrAttenuationRadius); return attenuation; } float GetAngleAttenuation(float3 L, float3 lightDir, float lightAngleScale, float lightAngleOffset) { float cd = dot(lightDir, L); float attenuation = saturate(cd * lightAngleScale + lightAngleOffset); // smooth the transition attenuation *= attenuation; return attenuation; } //----------------------------------------------------------------------------- // IES Helper //----------------------------------------------------------------------------- float2 GetIESTextureCoordinate(float3x3 lightToWord, float3 L) { // IES need to be sample in light space float3 dir = mul(lightToWord, -L); // Using matrix on left side do a transpose // convert to spherical coordinate float2 sphericalCoord; // .x is theta, .y is phi // Texture is encoded with cos(phi), scale from -1..1 to 0..1 sphericalCoord.y = (dir.z * 0.5) + 0.5; float theta = atan2(dir.y, dir.x); sphericalCoord.x = theta * INV_TWO_PI; return sphericalCoord; } //----------------------------------------------------------------------------- // Get local frame //----------------------------------------------------------------------------- // generate an orthonormalBasis from 3d unit vector. void GetLocalFrame(float3 N, out float3 tangentX, out float3 tangentY) { float3 upVector = abs(N.z) < 0.999 ? float3(0.0, 0.0, 1.0) : float3(1.0, 0.0, 0.0); tangentX = normalize(cross(upVector, N)); tangentY = cross(N, tangentX); } // TODO: test /* // http://orbit.dtu.dk/files/57573287/onb_frisvad_jgt2012.pdf void GetLocalFrame(float3 N, out float3 tangentX, out float3 tangentY) { if (N.z < -0.999) // Handle the singularity { tangentX = float3(0.0, -1.0, 0.0); tangentY = float3(-1.0, 0.0, 0.0); return ; } float a = 1.0 / (1.0 + N.z); float b = -N.x * N.y * a; tangentX = float3(1.0f - N.x * N.x * a , b, -N.x); tangentY = float3(b, 1.0f - N.y * N.y * a, -N.y); } */ #endif // UNITY_COMMON_LIGHTING_INCLUDED