mittsu 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -1
  3. data/README.md +1 -1
  4. data/lib/mittsu/cameras/orthographic_camera.rb +13 -0
  5. data/lib/mittsu/cameras/perspective_camera.rb +11 -0
  6. data/lib/mittsu/core/geometry.rb +12 -9
  7. data/lib/mittsu/core/object_3d.rb +33 -66
  8. data/lib/mittsu/lights/ambient_light.rb +8 -0
  9. data/lib/mittsu/lights/directional_light.rb +9 -0
  10. data/lib/mittsu/lights/hemisphere_light.rb +9 -0
  11. data/lib/mittsu/lights/point_light.rb +11 -0
  12. data/lib/mittsu/lights/spot_light.rb +13 -0
  13. data/lib/mittsu/loaders.rb +1 -0
  14. data/lib/mittsu/loaders/mtl_loader.rb +5 -12
  15. data/lib/mittsu/loaders/obj_loader.rb +212 -0
  16. data/lib/mittsu/loaders/obj_mtl_loader.rb +11 -207
  17. data/lib/mittsu/materials/material.rb +5 -2
  18. data/lib/mittsu/materials/mesh_basic_material.rb +0 -9
  19. data/lib/mittsu/math/color.rb +44 -104
  20. data/lib/mittsu/math/matrix3.rb +8 -1
  21. data/lib/mittsu/math/matrix4.rb +6 -0
  22. data/lib/mittsu/math/vector.rb +251 -0
  23. data/lib/mittsu/math/vector2.rb +14 -213
  24. data/lib/mittsu/math/vector3.rb +61 -351
  25. data/lib/mittsu/math/vector4.rb +45 -295
  26. data/lib/mittsu/objects/line.rb +12 -2
  27. data/lib/mittsu/objects/mesh.rb +18 -9
  28. data/lib/mittsu/renderers/glfw_window.rb +15 -13
  29. data/lib/mittsu/renderers/opengl/core/opengl_geometry.rb +253 -0
  30. data/lib/mittsu/renderers/opengl/core/opengl_object_3d.rb +131 -0
  31. data/lib/mittsu/renderers/opengl/lights/opengl_ambient_light.rb +26 -0
  32. data/lib/mittsu/renderers/opengl/lights/opengl_directional_light.rb +35 -0
  33. data/lib/mittsu/renderers/opengl/lights/opengl_hemisphere_light.rb +42 -0
  34. data/lib/mittsu/renderers/opengl/lights/opengl_light.rb +52 -0
  35. data/lib/mittsu/renderers/opengl/lights/opengl_point_light.rb +36 -0
  36. data/lib/mittsu/renderers/opengl/lights/opengl_spot_light.rb +47 -0
  37. data/lib/mittsu/renderers/opengl/materials/opengl_line_basic_material.rb +16 -0
  38. data/lib/mittsu/renderers/opengl/materials/opengl_material.rb +275 -0
  39. data/lib/mittsu/renderers/opengl/materials/opengl_mesh_basic_material.rb +69 -0
  40. data/lib/mittsu/renderers/opengl/materials/opengl_mesh_lambert_material.rb +29 -0
  41. data/lib/mittsu/renderers/opengl/materials/opengl_mesh_phong_material.rb +40 -0
  42. data/lib/mittsu/renderers/opengl/materials/opengl_shader_material.rb +11 -0
  43. data/lib/mittsu/renderers/opengl/objects/opengl_group.rb +8 -0
  44. data/lib/mittsu/renderers/opengl/objects/opengl_line.rb +54 -0
  45. data/lib/mittsu/renderers/opengl/objects/opengl_mesh.rb +77 -0
  46. data/lib/mittsu/renderers/opengl/opengl_buffer.rb +5 -0
  47. data/lib/mittsu/renderers/opengl/opengl_debug.rb +49 -7
  48. data/lib/mittsu/renderers/opengl/opengl_default_target.rb +54 -0
  49. data/lib/mittsu/renderers/opengl/opengl_geometry_group.rb +763 -0
  50. data/lib/mittsu/renderers/opengl/opengl_geometry_like.rb +130 -0
  51. data/lib/mittsu/renderers/opengl/opengl_helper.rb +161 -0
  52. data/lib/mittsu/renderers/opengl/opengl_implementations.rb +61 -0
  53. data/lib/mittsu/renderers/opengl/opengl_light_renderer.rb +43 -0
  54. data/lib/mittsu/renderers/opengl/opengl_mittsu_params.rb +53 -0
  55. data/lib/mittsu/renderers/opengl/opengl_program.rb +147 -296
  56. data/lib/mittsu/renderers/opengl/opengl_state.rb +3 -5
  57. data/lib/mittsu/renderers/opengl/plugins/shadow_map_plugin.rb +12 -10
  58. data/lib/mittsu/renderers/opengl/scenes/opengl_scene.rb +8 -0
  59. data/lib/mittsu/renderers/opengl/textures/opengl_compressed_texture.rb +21 -0
  60. data/lib/mittsu/renderers/opengl/textures/opengl_cube_texture.rb +75 -0
  61. data/lib/mittsu/renderers/opengl/textures/opengl_data_texture.rb +23 -0
  62. data/lib/mittsu/renderers/opengl/textures/opengl_texture.rb +111 -0
  63. data/lib/mittsu/renderers/opengl_render_target.rb +117 -2
  64. data/lib/mittsu/renderers/opengl_renderer.rb +653 -2978
  65. data/lib/mittsu/renderers/shaders/rbsl_loader.rb +166 -0
  66. data/lib/mittsu/renderers/shaders/shader_chunk.rb +6 -9
  67. data/lib/mittsu/renderers/shaders/shader_chunk/shadowmap_fragment.glsl +36 -37
  68. data/lib/mittsu/renderers/shaders/shader_lib.rb +26 -403
  69. data/lib/mittsu/renderers/shaders/shader_lib/basic/basic_fragment.rbsl +37 -0
  70. data/lib/mittsu/renderers/shaders/shader_lib/basic/basic_uniforms.rbslu +3 -0
  71. data/lib/mittsu/renderers/shaders/shader_lib/basic/basic_vertex.rbsl +33 -0
  72. data/lib/mittsu/renderers/shaders/shader_lib/cube/cube_fragment.rbsl +12 -0
  73. data/lib/mittsu/renderers/shaders/shader_lib/cube/cube_uniforms.rbslu +2 -0
  74. data/lib/mittsu/renderers/shaders/shader_lib/cube/cube_vertex.rbsl +12 -0
  75. data/lib/mittsu/renderers/shaders/shader_lib/depth_rgba/depth_rgba_fragment.rbsl +26 -0
  76. data/lib/mittsu/renderers/shaders/shader_lib/depth_rgba/depth_rgba_uniforms.rbslu +0 -0
  77. data/lib/mittsu/renderers/shaders/shader_lib/depth_rgba/depth_rgba_vertex.rbsl +12 -0
  78. data/lib/mittsu/renderers/shaders/shader_lib/lambert/lambert_fragment.rbsl +56 -0
  79. data/lib/mittsu/renderers/shaders/shader_lib/lambert/lambert_uniforms.rbslu +7 -0
  80. data/lib/mittsu/renderers/shaders/shader_lib/lambert/lambert_vertex.rbsl +37 -0
  81. data/lib/mittsu/renderers/shaders/shader_lib/phong/phong_fragment.rbsl +45 -0
  82. data/lib/mittsu/renderers/shaders/shader_lib/phong/phong_uniforms.rbslu +11 -0
  83. data/lib/mittsu/renderers/shaders/shader_lib/phong/phong_vertex.rbsl +43 -0
  84. data/lib/mittsu/renderers/shaders/shader_templates/fragment.glsl.erb +105 -0
  85. data/lib/mittsu/renderers/shaders/shader_templates/vertex.glsl.erb +143 -0
  86. data/lib/mittsu/renderers/shaders/uniforms_lib.rb +54 -55
  87. data/lib/mittsu/textures/texture.rb +5 -2
  88. data/lib/mittsu/version.rb +1 -1
  89. data/run_all_examples.sh +7 -0
  90. metadata +77 -28
  91. data/.ruby-version +0 -1
  92. data/lib/mittsu/core/hash_object.rb +0 -19
@@ -2,21 +2,23 @@ require 'opengl'
2
2
  require 'glfw'
3
3
 
4
4
  GLFW_LIB_EXT = OpenGL.get_platform == :OPENGL_PLATFORM_MACOSX ? 'dylib' : 'so'
5
- GLFW_LIB = begin
6
- "lib#{`pkg-config --libs-only-l glfw3`.gsub(/^-l/, '').chomp.strip}.#{GLFW_LIB_EXT}"
7
- rescue
8
- "libglfw.#{GLFW_LIB_EXT}"
9
- end
10
- GLFW_LIB_PATH = begin
11
- s = `pkg-config glfw3 --libs-only-L`.gsub(/^-L/, '').chomp.strip
12
- s.empty? ? nil : s
13
- rescue
14
- nil
15
- end
5
+ if OpenGL.get_platform != :OPENGL_PLATFORM_TEST
6
+ GLFW_LIB = begin
7
+ "lib#{`pkg-config --libs-only-l glfw3`.gsub(/^-l/, '').chomp.strip}.#{GLFW_LIB_EXT}"
8
+ rescue
9
+ "libglfw.#{GLFW_LIB_EXT}"
10
+ end
11
+ GLFW_LIB_PATH = begin
12
+ s = `pkg-config glfw3 --libs-only-L`.gsub(/^-L/, '').chomp.strip
13
+ s.empty? ? nil : s
14
+ rescue
15
+ nil
16
+ end
16
17
 
17
- GLFW.load_lib GLFW_LIB, GLFW_LIB_PATH
18
+ GLFW.load_lib GLFW_LIB, GLFW_LIB_PATH
18
19
 
19
- include GLFW
20
+ include GLFW
21
+ end
20
22
 
21
23
  module Mittsu
22
24
  module GLFW
@@ -0,0 +1,253 @@
1
+ require 'mittsu/renderers/opengl/opengl_geometry_like'
2
+
3
+ module Mittsu
4
+ class OpenGLGeometry
5
+ include OpenGLGeometryLike
6
+
7
+ attr_accessor :groups, :initted
8
+ attr_reader :id
9
+
10
+ def initialize(geometry, renderer)
11
+ @id = (@@id ||= 1).tap { @@id += 1 }
12
+
13
+ @geometry = geometry
14
+ @renderer = renderer
15
+ end
16
+
17
+ def init_geometry_groups(object)
18
+ object_impl = object.implementation(@renderer)
19
+ material = object.material
20
+ add_buffers = false
21
+
22
+ if @groups.nil? || @geometry.groups_need_update
23
+ @renderer.remove_opengl_object(object)
24
+
25
+ @groups = make_groups(material.is_a?(MeshFaceMaterial))
26
+
27
+ @geometry.groups_need_update = false
28
+ end
29
+
30
+ # create separate VBOs per geometry chunk
31
+
32
+ @groups.each do |geometry_group|
33
+ # initialize VBO on the first access
34
+ if geometry_group.vertex_buffer.nil?
35
+ geometry_group.create_mesh_buffers
36
+ geometry_group.init_mesh_buffers(object)
37
+
38
+ @geometry.vertices_need_update = true
39
+ @geometry.morph_targets_need_update = true
40
+ @geometry.elements_need_update = true
41
+ @geometry.uvs_need_update = true
42
+ @geometry.normals_need_update = true
43
+ @geometry.tangents_need_update = true
44
+ @geometry.colors_need_update = true
45
+
46
+ add_buffers = true
47
+ else
48
+ add_buffers = false
49
+ end
50
+
51
+ if add_buffers || !object_impl.active?
52
+ @renderer.add_opengl_object(geometry_group, object)
53
+ end
54
+ end
55
+
56
+ object_impl.active = true
57
+ end
58
+
59
+ def init_line_buffers(object)
60
+ nvertices = @geometry.vertices.length
61
+
62
+ @vertex_array = Array.new(nvertices * 3, 0.0) # Float32Array
63
+ @color_array = Array.new(nvertices * 3, 0.0) # Float32Array
64
+ @line_distance_array = Array.new(nvertices, 0.0) # Float32Array
65
+
66
+ @line_count = nvertices
67
+
68
+ init_custom_attributes(object)
69
+ end
70
+
71
+ def create_line_buffers
72
+ @vertex_array_object = glCreateVertexArray
73
+
74
+ @vertex_buffer = glCreateBuffer
75
+ @color_buffer = glCreateBuffer
76
+ @line_distance_buffer = glCreateBuffer
77
+
78
+ @renderer.info[:memory][:geometries] += 1
79
+ end
80
+
81
+ def set_line_buffers(hint)
82
+ if @geometry.vertices_need_update
83
+ @geometry.vertices.each_with_index do |vertex, v|
84
+ offset = v * 3
85
+
86
+ @vertex_array[offset] = vertex.x
87
+ @vertex_array[offset + 1] = vertex.y
88
+ @vertex_array[offset + 2] = vertex.z
89
+ end
90
+
91
+ glBindBuffer(GL_ARRAY_BUFFER, @vertex_buffer)
92
+ glBufferData_easy(GL_ARRAY_BUFFER, @vertex_array, hint)
93
+ end
94
+
95
+ if @geometry.colors_need_update
96
+ @geometry.colors.each_with_index do |color, c|
97
+ offset = c * 3
98
+
99
+ @color_array[offset] = color.r
100
+ @color_array[offset + 1] = color.g
101
+ @color_array[offset + 2] = color.b
102
+ end
103
+
104
+ glBindBuffer(GL_ARRAY_BUFFER, @color_buffer)
105
+ glBufferData_easy(GL_ARRAY_BUFFER, @color_array, hint)
106
+ end
107
+
108
+ if @geometry.line_distances_need_update
109
+ @geometry.line_distances.each_with_index do |l, d|
110
+ @line_distance_array[d] = l
111
+ end
112
+
113
+ glBindBuffer(GL_ARRAY_BUFFER, @line_distance_buffer)
114
+ glBufferData_easy(GL_ARRAY_BUFFER, @line_distance_array, hint)
115
+ end
116
+
117
+ if @custom_attributes
118
+ @custom_attributes.each do |custom_attribute|
119
+ offset = 0
120
+
121
+ values = custom_attribute.value
122
+
123
+ case custom_attribute.size
124
+ when 1
125
+ value.each_with_index do |value, ca|
126
+ custom_attribute.array[ca] = value
127
+ end
128
+ when 2
129
+ values.each_with_index do |value, ca|
130
+ custom_attribute[offset ] = value.x
131
+ custom_attribute[offset + 1] = value.y
132
+
133
+ offset += 2
134
+ end
135
+ when 3
136
+ if custom_attribute.type === :c
137
+ values.each_with_index do |value, ca|
138
+ custom_attribute[offset ] = value.r
139
+ custom_attribute[offset + 1] = value.g
140
+ custom_attribute[offset + 2] = value.b
141
+
142
+ offset += 3
143
+ end
144
+ else
145
+ values.each_with_index do |value, ca|
146
+ custom_attribute[offset ] = value.x
147
+ custom_attribute[offset + 1] = value.y
148
+ custom_attribute[offset + 2] = value.z
149
+
150
+ offset += 3
151
+ end
152
+ end
153
+ when 4
154
+ values.each_with_index do |value, ca|
155
+ custom_attribute[offset ] = value.x
156
+ custom_attribute[offset + 1] = value.y
157
+ custom_attribute[offset + 2] = value.z
158
+ custom_attribute[offset + 3] = value.w
159
+
160
+ offset += 4
161
+ end
162
+ end
163
+
164
+ glBindBuffer(GL_ARRAY_BUFFER, custom_attribute.buffer)
165
+ glBufferData_easy(GL_ARRAY_BUFFER, custom_attribute.array, hint)
166
+
167
+ custom_attribute.needs_update = false
168
+ end
169
+ end
170
+ end
171
+
172
+ private
173
+
174
+ def make_groups(uses_face_material = false)
175
+ max_vertices_in_group = 65535 # TODO: OES_element_index_uint ???
176
+
177
+ hash_map = {}
178
+
179
+ num_morph_targets = @geometry.morph_targets.length
180
+ num_morph_normals = @geometry.morph_normals.length
181
+
182
+ groups = {}
183
+ groups_list = []
184
+
185
+ @geometry.faces.each_with_index do |face, f|
186
+ material_index = uses_face_material ? face.material_index : 0
187
+
188
+ if !hash_map.include? material_index
189
+ hash_map[material_index] = { hash: material_index, counter: 0 }
190
+ end
191
+
192
+ group_hash = "#{hash_map[material_index][:hash]}_#{hash_map[material_index][:counter]}"
193
+
194
+ if !groups.include? group_hash
195
+ group = OpenGLGeometryGroup.new(material_index, num_morph_targets, num_morph_normals, @renderer)
196
+
197
+ groups[group_hash] = group
198
+ groups_list << group
199
+ end
200
+
201
+ if groups[group_hash].num_vertices + 3 > max_vertices_in_group
202
+ hash_map[material_index][:counter] += 1
203
+ group_hash = "#{hash_map[material_index][:hash]}_#{hash_map[material_index][:counter]}"
204
+
205
+ if !groups.include? group_hash
206
+ group = OpenGLGeometryGroup.new(material_index, num_morph_targets, num_morph_normals, @renderer)
207
+
208
+ groups[group_hash] = group
209
+ groups_list << group
210
+ end
211
+ end
212
+ groups[group_hash].faces3 << f
213
+ groups[group_hash].num_vertices += 3
214
+ end
215
+ groups_list
216
+ end
217
+
218
+ def init_custom_attributes(object)
219
+ material = object.material
220
+
221
+ nvertices = @geometry.vertices.length
222
+
223
+ if material.attributes
224
+ @custom_attributes_list ||= []
225
+
226
+ material.attributes.each do |(name, attribute)|
227
+ if !attribute[:_opengl_initialized] || attribute.create_unique_buffers
228
+ attribute[:_opengl_initialized] = true
229
+
230
+ size = case attribute.type
231
+ when :v2 then 2
232
+ when :v3 then 3
233
+ when :v4 then 4
234
+ when :c then 3
235
+ else 1
236
+ end
237
+
238
+ attribute.size = size
239
+
240
+ attribute.array = Array.new(nvertices * size) # Float32Array
241
+
242
+ attribute.buffer = glCreateBuffer
243
+ attribute.buffer.belongs_to_attribute = name
244
+
245
+ attribute.needs_update = true
246
+ end
247
+
248
+ @custom_attributes_list << attribute
249
+ end
250
+ end
251
+ end
252
+ end
253
+ end
@@ -0,0 +1,131 @@
1
+ module Mittsu
2
+ class OpenGLObject3D
3
+ attr_accessor :morph_target_influences
4
+ attr_reader :model_view_matrix
5
+ attr_writer :active
6
+
7
+ def initialize(object, renderer)
8
+ @object = object
9
+ @renderer = renderer
10
+ @_vector3 = Vector3.new
11
+ end
12
+
13
+ def active?
14
+ @active
15
+ end
16
+
17
+ def init
18
+ if !@initted
19
+ @initted = true
20
+ @model_view_matrix = Matrix4.new
21
+ @normal_matrix = Matrix3.new
22
+
23
+ @object.add_event_listener(:removed, @renderer.method(:on_object_removed))
24
+ end
25
+
26
+ geometry = @object.geometry
27
+
28
+ if geometry.nil?
29
+ # ImmediateRenderObject
30
+ else
31
+ geometry_impl = geometry.implementation(@renderer)
32
+ if !geometry_impl.initted
33
+ geometry_impl.initted = true
34
+ geometry.add_event_listener(:dispose, @renderer.method(:on_geometry_dispose))
35
+ if geometry.is_a?(BufferGeometry)
36
+ @renderer.info[:memory][:geometries] += 1
37
+ else
38
+ init_geometry
39
+ end
40
+ # TODO: when PointCloud exists
41
+ # when PointCloud
42
+ # if geometry[:_opengl_vertex_buffer].nil?
43
+ # create_particle_buffers(geometry)
44
+ # init_particle_buffers(geometry, object)
45
+ #
46
+ # geometry.vertices_need_update = true
47
+ # geometry.colors_need_update = true
48
+ # end
49
+ end
50
+ end
51
+
52
+ if !@active
53
+ @active = true
54
+
55
+ add_opengl_object
56
+ # TODO: when ImmediateRenderObject exists
57
+ # if object.is_a? ImmediateRenderObject || object.immediate_render_callback
58
+ # add_buffer_immediate(@renderer.instance_variable_get(:@_opengl_objects_immediate), @object)
59
+ # end
60
+ end
61
+ end
62
+
63
+ def project
64
+ return unless @object.visible
65
+ init
66
+
67
+ # TODO!!! FIXME!!!
68
+ opengl_objects = @renderer.instance_variable_get(:@_opengl_objects)[@object.id]
69
+
70
+ if opengl_objects && (!@object.frustum_culled || @renderer.object_in_frustum?(@object))
71
+ opengl_objects.each do |opengl_object|
72
+ # TODO!!! FIXME!!!
73
+ @renderer.send(:unroll_buffer_material, opengl_object)
74
+
75
+ opengl_object.render = true
76
+ if @renderer.sort_objects?
77
+ @_vector3.set_from_matrix_position(@object.matrix_world)
78
+ @_vector3.apply_projection(@renderer.proj_screen_matrix)
79
+
80
+ opengl_object[:z] = @_vector3.z
81
+ end
82
+ end
83
+ end
84
+
85
+ project_children
86
+ end
87
+
88
+ def setup_matrices(camera)
89
+ @model_view_matrix.multiply_matrices(camera.matrix_world_inverse, @object.matrix_world)
90
+ @normal_matrix.normal_matrix(@model_view_matrix)
91
+ @model_view_matrix
92
+ end
93
+
94
+ def load_uniforms_matrices(uniforms)
95
+ glUniformMatrix4fv(uniforms['modelViewMatrix'],
96
+ 1, GL_FALSE,
97
+ array_to_ptr_easy(@model_view_matrix.elements))
98
+
99
+ if uniforms['normalMatrix']
100
+ glUniformMatrix3fv(uniforms['normalMatrix'],
101
+ 1, GL_FALSE,
102
+ array_to_ptr_easy(@normal_matrix.elements))
103
+ end
104
+ end
105
+
106
+ def buffer_material(geometry_group)
107
+ material = @object.material
108
+ if material.is_a?(MeshFaceMaterial)
109
+ material.materials[geometry_group.material_index]
110
+ else
111
+ material
112
+ end
113
+ end
114
+
115
+ def init_geometry
116
+ # NOOP
117
+ end
118
+
119
+ def add_opengl_object
120
+ # NOOP
121
+ end
122
+
123
+ protected
124
+
125
+ def project_children
126
+ @object.children.each do |child|
127
+ child.implementation(@renderer).project
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,26 @@
1
+ module Mittsu
2
+ class OpenGLAmbientLight < OpenGLLight
3
+ TYPE = :ambient
4
+
5
+ class Cache < Struct.new(:length, :count, :value)
6
+ def initialize
7
+ super(0, 0, [0.0, 0.0, 0.0])
8
+ end
9
+
10
+ def reset
11
+ self.length = 0
12
+ self.value[0] = 0.0
13
+ self.value[1] = 0.0
14
+ self.value[2] = 0.0
15
+ end
16
+ end
17
+
18
+ def setup_specific(_)
19
+ @cache.value[0] += @light.color.r
20
+ @cache.value[1] += @light.color.g
21
+ @cache.value[2] += @light.color.b
22
+ end
23
+
24
+ def self.null_remaining_lights(_); end
25
+ end
26
+ end
@@ -0,0 +1,35 @@
1
+ module Mittsu
2
+ class OpenGLDirectionalLight < OpenGLLight
3
+ TYPE = :directional
4
+
5
+ class Cache < Struct.new(:length, :count, :colors, :positions)
6
+ def initialize
7
+ super(0, 0, [], [])
8
+ end
9
+
10
+ def reset
11
+ self.length = 0
12
+ end
13
+ end
14
+
15
+ def setup_specific(index)
16
+ offset = index * 3
17
+
18
+ @_direction.set_from_matrix_position(@light.matrix_world)
19
+ @_vector3.set_from_matrix_position(@light.target.matrix_world)
20
+ @_direction.sub(@_vector3)
21
+ @_direction.normalize
22
+
23
+ positions = @cache.positions
24
+ positions[offset] = @_direction.x
25
+ positions[offset + 1] = @_direction.y
26
+ positions[offset + 2] = @_direction.z
27
+
28
+ OpenGLHelper.set_color_linear(@cache.colors, offset, @light.color, @light.intensity)
29
+ end
30
+
31
+ def to_sym
32
+ :directional
33
+ end
34
+ end
35
+ end