summaryrefslogtreecommitdiffstats
path: root/src/extras/shaders/es2/light.inc.frag100
blob: 24766168be657440da756056cf030ca862e7b0c9 (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
const int MAX_LIGHTS = 2; // RPi: cannot use more than two as we run out of uniforms
const int TYPE_POINT = 0;
const int TYPE_DIRECTIONAL = 1;
const int TYPE_SPOT = 2;
struct Light {
    int type;
    FP vec3 position;
    FP vec3 color;
    FP float intensity;
    FP vec3 direction;
    FP vec3 attenuation;
    FP float cutOffAngle;
};
uniform Light lights[MAX_LIGHTS];
uniform int lightCount;

void adsModel(const in FP vec3 vpos, const in FP vec3 vnormal, const in FP vec3 eye, const in FP float shininess,
              out FP vec3 diffuseColor, out FP vec3 specularColor)
{
    diffuseColor = vec3(0.0);
    specularColor = vec3(0.0);

    FP vec3 n = normalize( vnormal );

    // 0
    if (lightCount < 1)
        return;
    FP vec3 s;
    FP float att = 1.0;
    if ( lights[0].type != TYPE_DIRECTIONAL ) {
        s = lights[0].position - vpos;
        if (length( lights[0].attenuation ) != 0.0) {
            FP float dist = length(s);
            att = 1.0 / (lights[0].attenuation.x + lights[0].attenuation.y * dist + lights[0].attenuation.z * dist * dist);
        }
        s = normalize( s );
        if ( lights[0].type == TYPE_SPOT ) {
            if ( degrees(acos(dot(-s, normalize(lights[0].direction))) ) > lights[0].cutOffAngle)
                att = 0.0;
        }
    } else {
        s = normalize( -lights[0].direction );
    }

    FP float diffuse = max( dot( s, n ), 0.0 );

    FP float specular = 0.0;
    if (diffuse > 0.0 && shininess > 0.0 && att > 0.0) {
        FP vec3 r = reflect( -s, n );
        FP vec3 v = normalize( eye - vpos );
        FP float normFactor = ( shininess + 2.0 ) / 2.0;
        specular = normFactor * pow( max( dot( r, v ), 0.0 ), shininess );
    }

    diffuseColor += att * lights[0].intensity * diffuse * lights[0].color;
    specularColor += att * specular;

    // 1
    if (lightCount < 2)
        return;
    att = 1.0;
    if ( lights[1].type != TYPE_DIRECTIONAL ) {
        s = lights[1].position - vpos;
        if (length( lights[1].attenuation ) != 0.0) {
            FP float dist = length(s);
            att = 1.0 / (lights[1].attenuation.x + lights[1].attenuation.y * dist + lights[1].attenuation.z * dist * dist);
        }
        s = normalize( s );
        if ( lights[1].type == TYPE_SPOT ) {
            if ( degrees(acos(dot(-s, normalize(lights[1].direction))) ) > lights[1].cutOffAngle)
                att = 0.0;
        }
    } else {
        s = normalize( -lights[1].direction );
    }

    diffuse = max( dot( s, n ), 0.0 );

    specular = 0.0;
    if (diffuse > 0.0 && shininess > 0.0 && att > 0.0) {
        FP vec3 r = reflect( -s, n );
        FP vec3 v = normalize( eye - vpos );
        FP float normFactor = ( shininess + 2.0 ) / 2.0;
        specular = normFactor * pow( max( dot( r, v ), 0.0 ), shininess );
    }

    diffuseColor += att * lights[1].intensity * diffuse * lights[1].color;
    specularColor += att * specular;
}