1 /**
2  * Copyright:       Copyright (C) 2018 Gabriel Gheorghe, All Rights Reserved
3  * Authors:         $(Gabriel Gheorghe)
4  * License:         $(LINK2 https://www.gnu.org/licenses/gpl-3.0.txt, GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007)
5  * Source:          $(LINK2 https://github.com/GabyForceQ/LibertyEngine/blob/master/source/liberty/framework/light/impl.d)
6  * Documentation:
7  * Coverage:
8 **/
9 module liberty.framework.light.impl;
10 
11 import liberty.framework.primitive.impl;
12 import liberty.framework.primitive.vertex;
13 import liberty.graphics.shader.constants;
14 import liberty.graphics.shader.impl;
15 import liberty.logger.impl;
16 import liberty.math.functions;
17 import liberty.math.transform;
18 import liberty.math.vector;
19 import liberty.scene.entity;
20 import liberty.scene.meta;
21 
22 /**
23  *
24 **/
25 final class Light : Entity {
26   mixin NodeBody;
27 
28   private {
29     static uint numberOfLights;
30 
31     uint index;
32     Vector3F color = Vector3F.one;
33     Vector3F attenuation = Vector3F(1.0f, 0.0f, 0.0f);
34   }
35 
36   /**
37    *
38   **/
39   this(string id) {
40     super(id);
41     register;
42 
43     component!Transform
44       .setLocation(0.0f, 200.0f, 0.0f);
45     
46     index = this.numberOfLights;
47     numberOfLights++;
48 
49     scene.lightMap[id] = this;
50   }
51 
52   ~this() {
53     this.numberOfLights--;
54   }
55 
56   /**
57    *
58    * Returns reference to this so it can be used in a stream.
59   **/
60   typeof(this) setColor(Vector3F color)   {
61     this.color = color;
62     return this;
63   }
64 
65   /**
66    *
67   **/
68   Vector3F getColor()   const {
69     return color;
70   }
71 
72   /**
73    *
74    * Returns reference to this so it can be used in a stream.
75   **/
76   typeof(this) setAttenuation(Vector3F attenuation)   {
77     this.attenuation = attenuation;
78     return this;
79   }
80 
81   /**
82    *
83   **/
84   Vector3F getAttenuation()   const {
85     return attenuation;
86   }
87 
88   /**
89    *
90   **/
91   uint getIndex()   const {
92     return index;
93   }
94 
95   /**
96    * Apply light to a primitive or terrain.
97    * Returns reference to this so it can be used in a stream.
98   **/
99   typeof(this) applyTo(string shaderId)
100   in (shaderId == "Primitive" || shaderId == "Terrain",
101     "You can apply light only on primitives and terrains.")
102   do {
103     import std.conv : to;
104 
105     if (index < 4) {
106       Shader
107         .getOrCreate(shaderId)
108         .getProgram
109         .loadUniform("uLightPosition[" ~ index.to!string ~ "]", component!Transform.getLocation)
110         .loadUniform("uLightColor[" ~ index.to!string ~ "]", color)
111         .loadUniform("uLightAttenuation[" ~ index.to!string ~ "]", attenuation)
112         .loadUniform("uShineDamper", 1.0f)
113         .loadUniform("uReflectivity", 0.0f);
114     } else
115       Logger.warning(shaderId ~ " shader can't render more than 4 lights.", typeof(this).stringof);
116 
117     return this;
118   }
119 }