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
@@ -0,0 +1,42 @@
1
+ module Mittsu
2
+ class OpenGLHemisphereLight < OpenGLLight
3
+ TYPE = :hemi
4
+
5
+ class Cache < Struct.new(:length, :count, :sky_colors, :ground_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
+ @_direction.normalize
20
+
21
+ positions = @cache.positions
22
+ positions[offset] = @_direction.x
23
+ positions[offset + 1] = @_direction.y
24
+ positions[offset + 2] = @_direction.z
25
+
26
+ sky_color = @light.color
27
+ ground_color = @light.ground_color
28
+
29
+ OpenGLHelper.set_color_linear(@cache.sky_colors, offset, sky_color, @light.intensity )
30
+ OpenGLHelper.set_color_linear(@cache.ground_colors, offset, ground_color, @light.intensity)
31
+ end
32
+
33
+ def self.null_remaining_lights(cache)
34
+ super(cache, cache.ground_colors)
35
+ super(cache, cache.sky_colors)
36
+ end
37
+
38
+ def to_sym
39
+ :hemi
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,52 @@
1
+ module Mittsu
2
+ class OpenGLLight < OpenGLObject3D
3
+ attr_accessor :camera_helper
4
+
5
+ def initialize(light, renderer)
6
+ super
7
+ @light = light
8
+ @light_renderer = renderer.light_renderer
9
+ @cache = @light_renderer.cache[type]
10
+
11
+ @_direction = Vector3.new
12
+ @_vector3 = Vector3.new
13
+ end
14
+
15
+ def type
16
+ self.class::TYPE
17
+ end
18
+
19
+ def setup
20
+ @cache.count += 1
21
+
22
+ return unless @light.visible
23
+ setup_specific(@cache.length)
24
+
25
+ @cache.length += 1
26
+ end
27
+
28
+ def project
29
+ return unless @light.visible
30
+ init
31
+ # TODO!!! FIXME!!!
32
+ @renderer.instance_variable_get(:@lights) << @light
33
+ project_children
34
+ end
35
+
36
+ def setup_specific
37
+ raise "Unknown Light Impl: #{@light.class} => #{self.class}"
38
+ end
39
+
40
+ def self.null_remaining_lights(cache, colors = nil)
41
+ colors ||= cache.colors
42
+ count = [colors.length, cache.count * 3].max
43
+ (cache.length * 3).upto(count - 1).each { |i|
44
+ colors[i] = 0.0
45
+ }
46
+ end
47
+
48
+ def to_sym
49
+ :other
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,36 @@
1
+ module Mittsu
2
+ class OpenGLPointLight < OpenGLLight
3
+ TYPE = :point
4
+
5
+ class Cache < Struct.new(:length, :count, :colors, :distances, :positions, :decays)
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
+ OpenGLHelper.set_color_linear(@cache.colors, offset, @light.color, @light.intensity)
19
+
20
+ @_vector3.set_from_matrix_position(@light.matrix_world)
21
+
22
+ positions = @cache.positions
23
+ positions[offset] = @_vector3.x
24
+ positions[offset + 1] = @_vector3.y
25
+ positions[offset + 2] = @_vector3.z
26
+
27
+ # distance is 0 if decay is 0, because there is no attenuation at all.
28
+ @cache.distances[index] = @light.distance
29
+ @cache.decays[index] = @light.distance.zero? ? 0.0 : @light.decay
30
+ end
31
+
32
+ def to_sym
33
+ :point
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,47 @@
1
+ module Mittsu
2
+ class OpenGLSpotLight < OpenGLLight
3
+ TYPE = :spot
4
+
5
+ class Cache < Struct.new(:length, :count, :colors, :directions, :distances, :positions, :exponents, :angles_cos, :decays)
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
+ OpenGLHelper.set_color_linear(@cache.colors, offset, @light.color, @light.intensity)
19
+
20
+ @_direction.set_from_matrix_position(@light.matrix_world)
21
+
22
+ positions = @cache.positions
23
+ positions[offset] = @_direction.x
24
+ positions[offset + 1] = @_direction.y
25
+ positions[offset + 2] = @_direction.z
26
+
27
+ @cache.distances[index] = @light.distance
28
+
29
+ @_vector3.set_from_matrix_position(@light.target.matrix_world)
30
+ @_direction.sub(@_vector3)
31
+ @_direction.normalize
32
+
33
+ directions = @cache.directions
34
+ directions[offset] = @_direction.x
35
+ directions[offset + 1] = @_direction.y
36
+ directions[offset + 2] = @_direction.z
37
+
38
+ @cache.angles_cos[index] = Math.cos(@light.angle)
39
+ @cache.exponents[index] = @light.exponent;
40
+ @cache.decays[index] = @light.distance.zero? ? 0.0 : @light.decay
41
+ end
42
+
43
+ def to_sym
44
+ :spot
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,16 @@
1
+ module Mittsu
2
+ class OpenGLLineBasicMaterial < OpenGLMaterial
3
+ def refresh_uniforms(uniforms)
4
+ uniforms['diffuse'].value = @material.color
5
+ uniforms['opacity'].value = @material.opacity
6
+ end
7
+
8
+ def init_shader
9
+ @shader = ShaderLib.create_shader(shader_id)
10
+ end
11
+
12
+ def shader_id
13
+ :basic
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,275 @@
1
+ module Mittsu
2
+ class OpenGLMaterial
3
+ # TODO: init_shader for these material-types
4
+ # MeshDepthMaterial => :depth, # TODO...
5
+ # MeshNormalMaterial => :normal, # TODO...
6
+ # LineDashedMaterial => :dashed, # TODO...
7
+ # PointCloudMaterial => :particle_basic # TODO...
8
+
9
+ attr_accessor :shadow_pass
10
+ attr_reader :shader, :uniforms_list
11
+
12
+ def initialize(material, renderer)
13
+ @material = material
14
+ @renderer = renderer
15
+ end
16
+
17
+ def init(lights, fog, object)
18
+ @material.add_event_listener(:dispose, @renderer.method(:on_material_dispose))
19
+
20
+ init_shader
21
+
22
+ @material.program = find_or_create_program(lights, fog, object)
23
+
24
+ count_supported_morph_attributes(@material.program.attributes)
25
+
26
+ @uniforms_list = get_uniforms_list
27
+ end
28
+
29
+ def set
30
+ if @material.transparent
31
+ @renderer.state.set_blending(@material.blending, @material.blend_equation, @material.blend_src, @material.blend_dst, @material.blend_equation_alpha, @material.blend_src_alpha, @material.blend_dst_alpha)
32
+ else
33
+ @renderer.state.set_blending(NoBlending)
34
+ end
35
+
36
+ @renderer.state.set_depth_test(@material.depth_test)
37
+ @renderer.state.set_depth_write(@material.depth_write)
38
+ @renderer.state.set_color_write(@material.color_write)
39
+ @renderer.state.set_polygon_offset(@material.polygon_offset, @material.polygon_offset_factor, @material.polygon_offset_units)
40
+ end
41
+
42
+ def needs_face_normals?
43
+ @material.shading == FlatShading
44
+ end
45
+
46
+ def clear_custom_attributes
47
+ @material.attributes.each do |attribute|
48
+ attribute.needs_update = false
49
+ end
50
+ end
51
+
52
+ def custom_attributes_dirty?
53
+ @material.attributes.each do |attribute|
54
+ return true if attribute.needs_update
55
+ end
56
+ false
57
+ end
58
+
59
+ def refresh_uniforms(_)
60
+ # NOOP
61
+ end
62
+
63
+ def needs_camera_position_uniform?
64
+ @material.env_map
65
+ end
66
+
67
+ def needs_view_matrix_uniform?
68
+ @material.skinning
69
+ end
70
+
71
+ def needs_lights?
72
+ @material.lights
73
+ end
74
+
75
+ protected
76
+
77
+ def init_shader
78
+ @shader = {
79
+ uniforms: @material.uniforms,
80
+ vertex_shader: @material.vertex_shader,
81
+ fragment_shader: @material.fragment_shader
82
+ }
83
+ end
84
+
85
+ def shader_id
86
+ nil
87
+ end
88
+
89
+ private
90
+
91
+ def allocate_lights(lights)
92
+ lights.reject { |light|
93
+ light.only_shadow || !light.visible
94
+ }.each_with_object({
95
+ directional: 0, point: 0, spot: 0, hemi: 0, other: 0
96
+ }) { |light, counts|
97
+ counts[light.implementation(@renderer).to_sym] += 1
98
+ }
99
+ end
100
+
101
+ def allocate_shadows(lights)
102
+ max_shadows = 0
103
+
104
+ lights.each do |light|
105
+ next unless light.cast_shadow
106
+
107
+ max_shadows += 1 if light.is_a?(SpotLight)
108
+ max_shadows += 1 if light.is_a?(DirectionalLight) && !light.shadow_cascade
109
+ end
110
+
111
+ max_shadows
112
+ end
113
+
114
+ def allocate_bones(object = nil)
115
+ if @renderer.supports_bone_textures? && object && object.skeleton && object.skeleton.use_vertex_texture
116
+ return 1024
117
+ end
118
+
119
+ # default for when object is not specified
120
+ # ( for example when prebuilding shader
121
+ # to be used with multiple objects )
122
+ #
123
+ # - leave some extra space for other uniforms
124
+ # - limit here is ANGLE's 254 max uniform vectors
125
+ # (up to 54 should be safe)
126
+
127
+ n_vertex_uniforms = (glGetParameter(GL_MAX_VERTEX_UNIFORM_COMPONENTS) / 4.0).floor
128
+ n_vertex_matrices = ((n_vertex_uniforms - 20) / 4.0).floor
129
+
130
+ max_bones = n_vertex_matrices
131
+
132
+ # TODO: when SkinnedMesh exists
133
+ # if !object.nil? && object.is_a?(SkinnedMesh)
134
+ # max_bones = [object.skeleton.bones.length, max_bones].min
135
+ #
136
+ # if max_bones < object.skeleton.bones.length
137
+ # puts "WARNING: OpenGLRenderer: too many bones - #{object.skeleton.bones.length}, this GPU supports just #{max_bones}"
138
+ # end
139
+ # end
140
+
141
+ max_bones
142
+ end
143
+
144
+ def count_supported_morph_attributes(attributes)
145
+ if @material.morph_targets
146
+ @material.num_supported_morph_normals = count_supported_morph_attribute(attributes, 'morphTarget', @renderer.max_morph_normals)
147
+ end
148
+ if @material.morph_normals
149
+ @material.num_supported_morph_normals = count_supported_morph_attribute(attributes, 'morphNormal', @renderer.max_morph_normals)
150
+ end
151
+ end
152
+
153
+ def count_supported_morph_attribute(attributes, base, max)
154
+ max.times.reduce do |num, i|
155
+ attribute = attributes["#{base}#{i}"]
156
+ attribute && attribute >= 0 ? num + 1 : num
157
+ end
158
+ end
159
+
160
+ def get_uniforms_list
161
+ @shader[:uniforms].map { |(key, uniform)|
162
+ location = @material.program.uniforms[key]
163
+ if location
164
+ [uniform, location]
165
+ end
166
+ }.compact
167
+ end
168
+
169
+ def program_parameters(lights, fog, object)
170
+ # heuristics to create shader paramaters according to lights in the scene
171
+ # (not to blow over max_lights budget)
172
+
173
+ max_light_count = allocate_lights(lights)
174
+ max_shadows = allocate_shadows(lights)
175
+ max_bones = allocate_bones(object)
176
+
177
+ {
178
+ supports_vertex_textures: @renderer.supports_vertex_textures?,
179
+
180
+ map: !!@material.map,
181
+ env_map: !!@material.env_map,
182
+ env_map_mode: @material.env_map && @material.env_map.mapping,
183
+ light_map: !!@material.light_map,
184
+ bump_map: !!@material.light_map,
185
+ normal_map: !!@material.normal_map,
186
+ specular_map: !!@material.specular_map,
187
+ alpha_map: !!@material.alpha_map,
188
+
189
+ combine: @material.combine,
190
+
191
+ vertex_colors: @material.vertex_colors,
192
+
193
+ fog: fog,
194
+ use_fog: @material.fog,
195
+ # fog_exp: fog.is_a?(FogExp2), # TODO: when FogExp2 exists
196
+
197
+ flat_shading: @material.shading == FlatShading,
198
+
199
+ size_attenuation: @material.size_attenuation,
200
+ logarithmic_depth_buffer: @renderer.logarithmic_depth_buffer,
201
+
202
+ skinning: @material.skinning,
203
+ max_bones: max_bones,
204
+ use_vertex_texture: @renderer.supports_bone_textures?,
205
+
206
+ morph_targets: @material.morph_targets,
207
+ morph_normals: @material.morph_normals,
208
+ max_morph_targets: @renderer.max_morph_targets,
209
+ max_morph_normals: @renderer.max_morph_normals,
210
+
211
+ max_dir_lights: max_light_count[:directional],
212
+ max_point_lights: max_light_count[:point],
213
+ max_spot_lights: max_light_count[:spot],
214
+ max_hemi_lights: max_light_count[:hemi],
215
+
216
+ max_shadows: max_shadows,
217
+ shadow_map_enabled: @renderer.shadow_map_enabled? && object.receive_shadow && max_shadows > 0,
218
+ shadow_map_type: @renderer.shadow_map_type,
219
+ shadow_map_debug: @renderer.shadow_map_debug,
220
+ shadow_map_cascade: @renderer.shadow_map_cascade,
221
+
222
+ alpha_test: @material.alpha_test,
223
+ metal: @material.metal,
224
+ wrap_around: @material.wrap_around,
225
+ double_sided: @material.side == DoubleSide,
226
+ flip_sided: @material.side == BackSide
227
+ }
228
+ end
229
+
230
+ def program_slug(parameters)
231
+ chunks = []
232
+
233
+ if shader_id
234
+ chunks << shader_id
235
+ else
236
+ chunks << @material.fragment_shader
237
+ chunks << @material.vertex_shader
238
+ end
239
+
240
+ if !@material.defines.nil?
241
+ @material.defines.each do |(name, define)|
242
+ chunks << name
243
+ chunks << define
244
+ end
245
+ end
246
+
247
+ parameters.each do |(name, parameter)|
248
+ chunks << name
249
+ chunks << parameter
250
+ end
251
+
252
+ chunks.join
253
+ end
254
+
255
+ def find_or_create_program(lights, fog, object)
256
+ parameters = program_parameters(lights, fog, object)
257
+ code = program_slug(parameters)
258
+
259
+ program = @renderer.programs.find do |program_info|
260
+ program_info.code == code
261
+ end
262
+
263
+ if program.nil?
264
+ program = OpenGLProgram.new(@renderer, code, @material, parameters)
265
+ @renderer.programs.push(program)
266
+
267
+ @renderer.info[:memory][:programs] = @renderer.programs.length
268
+ else
269
+ program.used_times += 1
270
+ end
271
+
272
+ program
273
+ end
274
+ end
275
+ end