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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
|
#ifndef LIGHT_H
#define LIGHT_H
#include "Lighting.h"
#include "Flare.h"
#include "ShadowSettings.h"
#include "Runtime/GameCode/Behaviour.h"
#include "Runtime/Math/Color.h"
#include "Runtime/Math/Vector3.h"
#include "Runtime/Geometry/AABB.h"
#include "Runtime/GfxDevice/GfxDeviceObjects.h"
#include "Runtime/GfxDevice/GfxDeviceConfigure.h"
#include "Runtime/Utilities/LinkedList.h"
#if UNITY_EDITOR
#include "Editor/Src/LightmapVisualization.h"
#endif
#include "Runtime/Math/Rect.h"
class Texture;
class GfxDevice;
class Light : public Behaviour, public ListElement
{
public:
REGISTER_DERIVED_CLASS (Light, Behaviour)
DECLARE_OBJECT_SERIALIZE (Light)
Light (MemLabelId label, ObjectCreationMode mode);
// ~Light(); declared-by-macro
static void InitializeClass ();
static void CleanupClass ();
// Tag class as sealed, this makes QueryComponent faster.
static bool IsSealedClass () { return true; }
virtual void Reset ();
// System interaction
virtual void AddToManager ();
virtual void RemoveFromManager ();
virtual void CheckConsistency ();
virtual void AwakeFromLoad(AwakeFromLoadMode mode);
void TransformChanged ();
LightType GetType() const { return static_cast<LightType>( m_Type ); }
void SetType (LightType type);
/// How to render this light.
enum RenderMode
{
kRenderAuto, ///< Automatic
kRenderImportant, ///< This light is important
kRenderNotImportant, ///< This light is not very important
kRenderModeCount // keep this last!
};
/// Get the render mode hint for this light
int GetRenderMode() const { return m_RenderMode; }
void SetRenderMode (int mode) { m_RenderMode = mode; SetDirty(); m_GfxLightValid = false; }
enum Lightmapping
{
kLightmappingRealtimeOnly = 0, // light is not baked, realtime only
kLightmappingAuto = 1, // light is baked in the dual lightmap style
kLightmappingBakedOnly = 2 // light is fully baked, not rendering in realtime at all
};
void SetLightmapping (int mode) { m_Lightmapping = mode; SetDirty(); m_GfxLightValid = false; }
inline Lightmapping GetLightmappingForRender() const;
Lightmapping GetLightmappingForBake() const;
void SetActuallyLightmapped (bool v);
bool GetActuallyLightmapped() const { return m_ActuallyLightmapped; }
/// Get the full range of the light.
float GetRange() const { return m_Range; }
void SetRange (float range) { m_Range = std::max(0.0F, range); SetDirty (); m_GfxLightValid = false; Precalc (); }
/// Get the spot angle in degrees.
float GetSpotAngle() const { return m_SpotAngle; }
void SetSpotAngle (float angle) { m_SpotAngle = angle; CheckConsistency(); SetDirty (); m_GfxLightValid = false; Precalc (); }
float GetCookieSize() const { return m_CookieSize; }
void SetCookieSize (float size) { m_CookieSize = size; CheckConsistency(); SetDirty (); m_GfxLightValid = false; Precalc (); }
// range * this value = end side length
float GetCotanHalfSpotAngle () const { return m_CotanHalfSpotAngle; }
// range * this value = diagonal side length
float GetInvCosHalfSpotAngle () const { return m_InvCosHalfSpotAngle; }
/// Get/set the cookie used for the light
void SetCookie (Texture *tex);
Texture *GetCookie () const { return m_Cookie; }
/// Get/set the lens flare used
void SetFlare (Flare *flare);
Flare *GetFlare () { return m_Flare; }
const ColorRGBAf& GetColor () const { return m_Color; }
void SetColor (const ColorRGBAf& c);
ColorRGBAf GetConvertedFinalColor() const { return m_ConvertedFinalColor; }
float GetIntensity() const { return m_Intensity; }
void SetIntensity( float i );
float GetShadowStrength() const { return m_Shadows.m_Strength; }
void SetShadowStrength( float f ) { m_Shadows.m_Strength = f; SetDirty(); }
ShadowType GetShadows() const { return static_cast<ShadowType>(m_Shadows.m_Type); }
void SetShadows( int v );
int GetShadowResolution() const { return m_Shadows.m_Resolution; }
void SetShadowResolution( int v ) { m_Shadows.m_Resolution = v; SetDirty(); }
float GetShadowBias() const { return m_Shadows.m_Bias; }
void SetShadowBias( float v ) { m_Shadows.m_Bias = v; SetDirty(); }
float GetShadowSoftness() const { return m_Shadows.m_Softness; }
void SetShadowSoftness (float v) { m_Shadows.m_Softness = v; SetDirty(); }
float GetShadowSoftnessFade() const { return m_Shadows.m_SoftnessFade; }
void SetShadowSoftnessFade (float v) { m_Shadows.m_SoftnessFade = v; SetDirty(); }
int GetFinalShadowResolution() const;
#if UNITY_EDITOR
int GetShadowSamples() const { return m_ShadowSamples; }
void SetShadowSamples (int samples) { m_ShadowSamples = samples; }
float GetShadowRadius() const { return m_ShadowRadius; }
void SetShadowRadius (float radius) { m_ShadowRadius = radius; }
float GetShadowAngle() const { return m_ShadowAngle; }
void SetShadowAngle (float angle) { m_ShadowAngle = angle; }
float GetIndirectIntensity() const { return m_IndirectIntensity; }
void SetIndirectIntensity (float intensity) { m_IndirectIntensity = intensity; }
Vector2f GetAreaSize() const { return m_AreaSize; }
void SetAreaSize(const Vector2f& areaSize) { m_AreaSize = areaSize; }
#endif
/// Calculate the quadratic attenuation factor for a light with a specified range
/// @param range the range of the light
/// @return the quadratic attenuation factor
static float CalcQuadFac (float range);
// Attenuation function: inverse quadratic. distSqr is over 0..1 range
static float AttenuateNormalized(float distSqr);
// Get the result of attenuation for a squared distance from the light
float AttenuateApprox (float sqrDist) const;
// Set up this light as GfxDevice fixed function per-vertex light.
// IMPORTANT: Assumes the modelview matrix has been set up to be the world2camera matrix.
void SetupVertexLight (int lightNo, float visibilityFade);
void SetLightKeyword();
void SetPropsToShaderLab (float blend) const;
// Set up the halo for the light.
void SetupHalo ();
// Set up the flare for the light.
void SetupFlare ();
void SetCullingMask (int mask) { m_CullingMask.m_Bits = mask; SetDirty(); }
int GetCullingMask () const { return m_CullingMask.m_Bits; }
// Precalc all non-changing shaderlab values.
void Precalc ();
const Vector3f& GetWorldPosition() const { return m_WorldPosition; }
const Matrix4x4f& GetWorldToLocalMatrix() const { return m_World2Local; }
enum AttenuationMode
{
kSpotCookie, // 2D cookie projected in spot light's cone
kPointFalloff, // Attenuation for a point light
kDirectionalCookie, // Cookie projected from a directional light
kUnused // The attenuation texture is not used
};
void GetMatrix (const Matrix4x4f* __restrict object2light, Matrix4x4f* __restrict outMatrix) const;
bool IsValidToRender() const;
private:
void UpdateSpotAngleValues ()
{
float halfSpotRad = Deg2Rad(m_SpotAngle * 0.5f);
float cs = cosf(halfSpotRad);
float ss = sinf(halfSpotRad);
m_CotanHalfSpotAngle = cs / ss;
m_InvCosHalfSpotAngle = 1.0f / cs;
}
void ComputeGfxLight (GfxVertexLight& gfxLight) const;
private:
Matrix4x4f m_World2Local;
Vector3f m_WorldPosition;
ShadowSettings m_Shadows; ///< Shadow settings.
ColorRGBAf m_Color;
ColorRGBAf m_ConvertedFinalColor;
PPtr<Flare> m_Flare; ///< Does the light have a flare?
PPtr<Texture> m_Cookie; ///< Custom cookie (optional).
BitField m_CullingMask; ///< The mask used for selectively lighting objects in the scene.
float m_Intensity; ///< Light intensity range {0.0, 8.0}
float m_Range; ///< Light range
float m_SpotAngle; ///< Angle of the spotlight cone.
float m_CookieSize; ///< Cookie size for directional lights.
float m_CotanHalfSpotAngle; // cotangent of half of the spot angle
float m_InvCosHalfSpotAngle; // 1/cos of half of the spot angle
int m_RenderMode; ///< enum { Auto, Important, Not Important } Rendering mode for the light.
int m_Lightmapping; ///< enum { RealtimeOnly, Auto, BakedOnly } Is light baked into lightmaps?
int m_Type; ///< enum { Spot, Directional, Point, Area (baked only) } Light type
bool m_DrawHalo; ///< Does the light have a halo?
bool m_ActuallyLightmapped; // Is it actually lightmapped already?
#if UNITY_EDITOR
int m_ShadowSamples; // number of samples for lightmapper shadow calculations
float m_ShadowRadius; // radius of the light source for lightmapper shadow calculations (point and spot lights)
float m_ShadowAngle; // angle of the cone for lightmapper shadow rays (directional lights)
float m_IndirectIntensity; // aka bounce intensity - a multiplier for the indirect light
Vector2f m_AreaSize; // size of area light's rectangle
#endif
PPtr<Texture> m_AttenuationTexture;
AttenuationMode m_AttenuationMode;
LightKeywordMode m_KeywordMode; // The current keyword used by the light
int m_HaloHandle, m_FlareHandle;
GfxVertexLight m_CachedGfxLight;
bool m_GfxLightValid;
};
void SetupVertexLights(const std::vector<Light*>& lights);
void SetLightScissorRect (const Rectf& lightRect, const Rectf& viewPort, bool intoRT, GfxDevice& device);
void ClearScissorRect (bool oldScissor, const int oldRect[4], GfxDevice& device);
// Inline this; called a lot in light culling.
inline Light::Lightmapping Light::GetLightmappingForRender() const
{
if (m_Type == kLightArea)
return kLightmappingBakedOnly;
// all lights behave as realtime only if no lightmaps have been baked yet or if lightmaps are disabled
return m_ActuallyLightmapped
#if UNITY_EDITOR
&& GetLightmapVisualization().GetUseLightmapsForRendering()
#endif
? static_cast<Lightmapping>(m_Lightmapping) : kLightmappingRealtimeOnly;
}
#endif
|