mittsu 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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