Class: Engine::Components::SpotLight

Inherits:
Engine::Component show all
Includes:
MatrixHelpers
Defined in:
lib/engine/components/spot_light.rb

Instance Attribute Summary collapse

Attributes inherited from Engine::Component

#game_object

Class Method Summary collapse

Instance Method Summary collapse

Methods included from MatrixHelpers

#look_at, #ortho, #perspective

Methods inherited from Engine::Component

#_erase!, #destroy, #destroyed?, destroyed_components, erase_destroyed_components, method_added, #renderer?, #set_game_object, #ui_renderer?

Methods included from Serializable

allowed_class?, get_class, included, register_class, #uuid

Instance Attribute Details

#cast_shadowsObject

Returns the value of attribute cast_shadows.



9
10
11
# File 'lib/engine/components/spot_light.rb', line 9

def cast_shadows
  @cast_shadows
end

#colourObject

Returns the value of attribute colour.



9
10
11
# File 'lib/engine/components/spot_light.rb', line 9

def colour
  @colour
end

#inner_angleObject

Returns the value of attribute inner_angle.



9
10
11
# File 'lib/engine/components/spot_light.rb', line 9

def inner_angle
  @inner_angle
end

#outer_angleObject

Returns the value of attribute outer_angle.



9
10
11
# File 'lib/engine/components/spot_light.rb', line 9

def outer_angle
  @outer_angle
end

#rangeObject

Returns the value of attribute range.



9
10
11
# File 'lib/engine/components/spot_light.rb', line 9

def range
  @range
end

#shadow_layer_indexObject

Returns the value of attribute shadow_layer_index.



9
10
11
# File 'lib/engine/components/spot_light.rb', line 9

def shadow_layer_index
  @shadow_layer_index
end

Class Method Details

.spot_lightsObject



86
87
88
# File 'lib/engine/components/spot_light.rb', line 86

def self.spot_lights
  @spot_lights ||= []
end

Instance Method Details

#awakeObject



11
12
13
14
15
16
17
18
19
# File 'lib/engine/components/spot_light.rb', line 11

def awake
  @range ||= 300
  @colour ||= [1.0, 1.0, 1.0]
  @inner_angle ||= 12.5
  @outer_angle ||= 17.5
  @cast_shadows = false if @cast_shadows.nil?
  @shadow_layer_index = nil
  @cached_light_space_matrix = nil
end

#compute_light_space_matrixObject



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/engine/components/spot_light.rb', line 63

def compute_light_space_matrix
  light_pos = position
  light_dir = direction
  target = light_pos + light_dir

  # Choose up vector that's not parallel to light direction
  # When light points mostly along Y axis, use Z as up instead
  up = if light_dir[1].abs > 0.9
    Vector[0, 0, 1]
  else
    Vector[0, 1, 0]
  end

  view_matrix = look_at(light_pos, target, up)

  # Perspective projection based on spotlight cone angle
  fov = (@outer_angle * 2.0 + 5.0) * Math::PI / 180.0
  # near/far ratio affects depth precision
  proj_matrix = perspective(fov, 1.0, shadow_near, shadow_far)

  (proj_matrix * view_matrix).transpose
end

#destroy!Object



25
26
27
# File 'lib/engine/components/spot_light.rb', line 25

def destroy!
  SpotLight.spot_lights.delete(self)
end

#directionObject



46
47
48
# File 'lib/engine/components/spot_light.rb', line 46

def direction
  game_object.local_to_world_direction(Vector[0, 0, 1]).normalize
end

#inner_cutoffObject



29
30
31
# File 'lib/engine/components/spot_light.rb', line 29

def inner_cutoff
  Math.cos(@inner_angle * Math::PI / 180.0)
end

#light_space_matrixObject



54
55
56
# File 'lib/engine/components/spot_light.rb', line 54

def light_space_matrix
  @cached_light_space_matrix ||= compute_light_space_matrix
end

#outer_cutoffObject



33
34
35
# File 'lib/engine/components/spot_light.rb', line 33

def outer_cutoff
  Math.cos(@outer_angle * Math::PI / 180.0)
end

#positionObject



50
51
52
# File 'lib/engine/components/spot_light.rb', line 50

def position
  game_object.local_to_world_coordinate(Vector[0, 0, 0])
end

#shadow_farObject



41
42
43
44
# File 'lib/engine/components/spot_light.rb', line 41

def shadow_far
  # Factor of 2 needed to match shadow range with spotlight attenuation range
  @range * 2.0
end

#shadow_nearObject



37
38
39
# File 'lib/engine/components/spot_light.rb', line 37

def shadow_near
  @range * 0.01
end

#startObject



21
22
23
# File 'lib/engine/components/spot_light.rb', line 21

def start
  SpotLight.spot_lights << self
end

#update(delta_time) ⇒ Object



58
59
60
61
# File 'lib/engine/components/spot_light.rb', line 58

def update(delta_time)
  # Clear cache each frame so matrix is recomputed if light moves
  @cached_light_space_matrix = nil
end