summaryrefslogtreecommitdiffstats
path: root/res/effectlib/sampleLight.glsllib
blob: 74bd733ac574db032e5dab0083c1706004c89042 (plain)
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
#ifndef SAMPLE_LIGHT_GLSLLIB
#define SAMPLE_LIGHT_GLSLLIB

#define MAX_NUM_SHADOWS 8

#ifndef UIC_ENABLE_SSM
#define UIC_ENABLE_SSM 0
#endif

#include "SSAOCustomMaterial.glsllib"
#if UIC_ENABLE_SSM
#include "shadowMapping.glsllib"
#endif

#include "funcsampleLightVars.glsllib"

#if UIC_ENABLE_SSM
uniform sampler2D shadowMaps[MAX_NUM_SHADOWS];
uniform samplerCube shadowCubes[MAX_NUM_SHADOWS];
uniform int uNumShadowMaps;
uniform int uNumShadowCubes;
#endif

void sampleLight(in LightSource light,
                 in vec3 pos,
                 out vec3 wi,
                 out vec3 opAmbient,
                 out vec3 opDiffuse,
                 out vec3 opSpecular)
{
  float att = 1.0;
  if (light.position.w == 0.0f)  // directional light
  {
    wi = normalize(light.position.xyz);
#if UIC_ENABLE_SSM
    if ( light.shadowIdx >= 0 )
      att *= sampleOrthographic( shadowMaps[light.shadowIdx], light.shadowControls, light.shadowView, pos, vec2(1.0, light.shadowControls.z) );
#endif
  }
  else if (light.width > 0.01f && light.height > 0.01f) // area light
  {
      // This approach is based on the 1994 Tech Report by James Arvo --
      // The Irradiance Jacobian for Partially Occluded Polyhedral Sources
      // The nice thing about this approach is that it extends to arbitrary geometry (if we choose to support it),
      // and accounts for distance & geometric attenuation automatically.
      // Downsides -- only really works for diffuse reflection, does not account properly for an area light that
      // intersects its receiver, in which case it illuminates as if the light source is two-sided Lambertian emitter.
      vec3 v0 = light.position.xyz - (light.right.xyz * light.width * 0.5) - (light.up.xyz * light.height * 0.5);
      vec3 v1 = light.position.xyz - (light.right.xyz * light.width * 0.5) + (light.up.xyz * light.height * 0.5);
      vec3 v2 = light.position.xyz + (light.right.xyz * light.width * 0.5) + (light.up.xyz * light.height * 0.5);
      vec3 v3 = light.position.xyz + (light.right.xyz * light.width * 0.5) - (light.up.xyz * light.height * 0.5);

      v0 = normalize( v0 - pos );  v1 = normalize( v1 - pos );  v2 = normalize( v2 - pos );  v3 = normalize( v3 - pos );

      float a01 = acos( clamp( dot(v0, v1), -1.0, 1.0 ) );
      float a12 = acos( clamp( dot(v1, v2), -1.0, 1.0 ) );
      float a23 = acos( clamp( dot(v2, v3), -1.0, 1.0 ) );
      float a30 = acos( clamp( dot(v3, v0), -1.0, 1.0 ) );

      wi = vec3( 0.0 );
      wi -= normalize(cross( v0, v1 )) * a01;
      wi -= normalize(cross( v1, v2 )) * a12;
      wi -= normalize(cross( v2, v3 )) * a23;
      wi -= normalize(cross( v3, v0 )) * a30;

      att = length(wi) * 0.15915494309;   // solid angle / 2*pi
      wi = normalize(wi);
      att *= clamp( dot( pos - light.position.xyz, light.direction.xyz ), 0.0, 1.0 );
#if UIC_ENABLE_SSM
      if ( light.shadowIdx >= 0 )
        att *= sampleCubemap( shadowCubes[light.shadowIdx], light.shadowControls, light.shadowView, light.position.xyz, pos, vec2(1.0, light.shadowControls.z) );
#endif
  }
  else  // point or spot light
  {
    wi = light.position.xyz - pos;
    float dist = length(wi);
    wi = wi / dist;  // == normalize(wi);
    att = 1.0f / (light.constantAttenuation + (light.linearAttenuation + light.quadraticAttenuation * dist) * dist);
    /*
    if (light.spotCutoff < 180.0f) // spot light
    {
      float spot = max(0.0f, dot(wi, -light.direction.xyz));
      att *= (spot >= cos(light.spotCutoff * PI / 180.0f)) ? pow(spot, light.spotExponent) : 0.0f;
    }
    */
#if UIC_ENABLE_SSM
    if ( light.shadowIdx >= 0 )
      att *= sampleCubemap( shadowCubes[light.shadowIdx], light.shadowControls, light.shadowView, light.position.xyz, pos, vec2(1.0, light.shadowControls.z) );
#endif
  }
  float shadow = customMaterialShadow( -light.direction.xyz, pos );
  opAmbient  = att * light.ambient.xyz;
  opDiffuse  = att * shadow * light.diffuse.xyz;
  opSpecular = att * shadow * light.specular.xyz;
}

#include "sampleArea.glsllib"

#endif