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
@@ -1,4 +1,3 @@
1
-
2
1
  require 'opengl'
3
2
  require 'glfw'
4
3
  require 'fiddle'
@@ -7,244 +6,73 @@ OpenGL.load_lib
7
6
 
8
7
  require 'mittsu'
9
8
  require 'mittsu/renderers/glfw_window'
9
+ require 'mittsu/renderers/opengl/opengl_implementations'
10
10
  require 'mittsu/renderers/opengl/opengl_debug'
11
+ require 'mittsu/renderers/opengl/opengl_helper'
11
12
  require 'mittsu/renderers/opengl/opengl_program'
12
13
  require 'mittsu/renderers/opengl/opengl_state'
14
+ require 'mittsu/renderers/opengl/opengl_geometry_group'
15
+ require 'mittsu/renderers/opengl/opengl_light_renderer'
16
+ require 'mittsu/renderers/opengl/opengl_default_target'
17
+ require 'mittsu/renderers/opengl/opengl_buffer'
13
18
  require 'mittsu/renderers/opengl/plugins/shadow_map_plugin'
14
19
  require 'mittsu/renderers/shaders/shader_lib'
15
20
  require 'mittsu/renderers/shaders/uniforms_utils'
16
21
 
17
- include OpenGL
22
+ include ENV['DEBUG'] ? OpenGLDebug : OpenGL
23
+ include Mittsu::OpenGLHelper
24
+
25
+ require 'mittsu/renderers/opengl/opengl_mittsu_params'
18
26
 
19
27
  module Mittsu
20
28
  class OpenGLRenderer
21
29
  attr_accessor :auto_clear, :auto_clear_color, :auto_clear_depth, :auto_clear_stencil, :sort_objects, :gamma_factor, :gamma_input, :gamma_output, :shadow_map_enabled, :shadow_map_type, :shadow_map_cull_face, :shadow_map_debug, :shadow_map_cascade, :max_morph_targets, :max_morph_normals, :info, :pixel_ratio, :window, :width, :height, :state
22
30
 
31
+ attr_reader :logarithmic_depth_buffer, :max_morph_targets, :max_morph_normals, :shadow_map_type, :shadow_map_debug, :shadow_map_cascade, :programs, :light_renderer, :proj_screen_matrix
32
+
23
33
  def initialize(parameters = {})
24
34
  puts "OpenGLRenderer (Revision #{REVISION})"
25
35
 
26
- @pixel_ratio = 1.0
27
-
28
- @precision = parameters.fetch(:precision, 'highp') # not sure if OpenGL works with the whole 'highp' thing...
29
- @_alpha = parameters.fetch(:alpha, false)
30
- @_depth = parameters.fetch(:depth, true)
31
- @_stencil = parameters.fetch(:stencil, true)
32
- @_antialias = parameters.fetch(:antialias, false)
33
- @_premultiplied_alpha = parameters.fetch(:premultiplied_alpha, true)
34
- @_preserve_drawing_buffer = parameters.fetch(:preserve_drawing_buffer, false)
35
- @_logarithmic_depth_buffer = parameters.fetch(:logarithmic_depth_buffer, false)
36
-
37
- @_clear_color = Color.new(0x000000)
38
- @_clear_alpha = 0.0
39
-
40
- @width = parameters.fetch(:width, 800)
41
- @height = parameters.fetch(:height, 600)
42
- @title = parameters.fetch(:title, "Mittsu #{REVISION}")
43
-
44
- @lights = []
45
-
46
- @_opengl_objects = {}
47
- @_opengl_objects_immediate = []
48
-
49
- @opaque_objects = []
50
- @transparent_objects = []
51
-
52
- @sprites = []
53
- @lens_flares = []
54
-
55
- # public properties
56
-
57
- # @dom_element = _canvas
58
- # @context = nil
59
-
60
- # clearing
61
-
62
- @auto_clear = true
63
- @auto_clear_color = true
64
- @auto_clear_depth = true
65
- @auto_clear_stencil = true
66
-
67
- # scene graph
36
+ fetch_parameters(parameters)
68
37
 
38
+ @pixel_ratio = 1.0
69
39
  @sort_objects = true
70
40
 
71
- # physically based shading
72
-
73
- @gamma_factor = 2.0 # backwards compat???
74
- @gamma_input = false
75
- @gamma_output = false
76
-
77
- # shadow map
78
-
79
- @shadow_map_enabled = false
80
- @shadow_map_type = PCFShadowMap
81
- @shadow_map_cull_face = CullFaceFront
82
- @shadow_map_debug = false
83
- @shadow_map_cascade = false
84
-
85
- # morphs
86
-
87
- @max_morph_targets = 8
88
- @max_morph_normals = 4
89
-
90
- # info
91
-
92
- @info = {
93
- memory: {
94
- programs: 0,
95
- geometries: 0,
96
- textures: 0
97
- },
98
- render: {
99
- calls: 0,
100
- vertices: 0,
101
- faces: 0,
102
- points: 0
103
- }
104
- }
105
-
106
- # internal properties
107
-
108
- @_programs = []
109
-
110
- # internal state cache
111
-
112
- @_current_program = nil
113
- @_current_framebuffer = nil
114
- @_current_material_id = -1
115
- @_current_geometry_program = ''
116
- @_current_camera = nil
117
-
118
- @_used_texture_units = 0
119
- @_viewport_x = 0
120
- @_viewport_y = 0
121
- @_current_width = 0
122
- @_current_height = 0
123
-
124
- # frustum
41
+ init_collections
42
+ init_clearing
43
+ init_gamma
44
+ init_shadow_properties
45
+ init_morphs
46
+ init_info
47
+ init_state_cache
48
+ init_camera_matrix_cache
125
49
 
126
- @_frustum = Frustum.new
127
-
128
- # camera matrices cache
129
-
130
- @_proj_screen_matrix = Matrix4.new
131
- @_vector3 = Vector3.new
132
-
133
- # light arrays cache
134
-
135
- @_direction = Vector3.new
136
- @_lights_need_update = true
137
- # TODO: re-imagine this thing as a bunch of classes...
138
- @_lights = {
139
- ambient: [0, 0, 0],
140
- directional: { length: 0, colors: [], positions: [] },
141
- point: { length: 0, colors: [], positions: [], distances: [], decays: [] },
142
- spot: { length: 0, colors: [], positions: [], distances: [], directions: [], angles_cos: [], exponents: [], decays: [] },
143
- hemi: { length: 0, sky_colors: [], ground_colors: [], positions: []}
144
- }
145
-
146
- @geometry_groups = {}
147
- @geometry_group_counter = 0
148
-
149
- @shader_ids = {
150
- # MeshDepthMaterial => :depth, # TODO...
151
- # MeshNormalMaterial => :normal, # TODO...
152
- MeshBasicMaterial => :basic,
153
- MeshLambertMaterial => :lambert,
154
- MeshPhongMaterial => :phong,
155
- LineBasicMaterial => :basic,
156
- # LineDashedMaterial => :dashed, # TODO...
157
- # PointCloudMaterial => :particle_basic # TODO...
158
- }
50
+ @light_renderer = OpenGLLightRenderer.new(self)
159
51
 
160
- # initialize
52
+ create_window
161
53
 
162
- begin
163
- # attributes = {
164
- # alpha: _alpha,
165
- # depth: _depth,
166
- # stencil: _stencil,
167
- # antialias: _antialias,
168
- # premultiplied_alpha: _premultiplied_alpha,
169
- # preserve_drawing_buffer: _preserve_drawing_buffer
170
- # }
54
+ @state = OpenGLState.new
171
55
 
172
- @window = GLFW::Window.new(@width, @height, @title)
173
-
174
- @_viewport_width, @_viewport_height = *(@window.framebuffer_size)
175
-
176
- # TODO: handle losing opengl context??
177
- rescue => error
178
- puts "ERROR: Mittsu::OpenGLRenderer: #{error.inspect}"
179
- end
180
-
181
- @state = OpenGLState.new(self.method(:param_mittsu_to_gl))
182
-
183
- # TODO: get shader precision format???
184
56
  # TODO: load extensions??
185
57
 
186
58
  reset_gl_state
187
59
  set_default_gl_state
188
60
 
189
- # GPU capabilities
190
-
191
- @_max_textures = get_gl_parameter(GL_MAX_TEXTURE_IMAGE_UNITS)
192
- @_max_vertex_textures = get_gl_parameter(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS)
193
- @_max_texture_size = get_gl_parameter(GL_MAX_TEXTURE_SIZE)
194
- @_max_cubemap_size = get_gl_parameter(GL_MAX_CUBE_MAP_TEXTURE_SIZE)
195
-
196
- @_supports_vertex_textures = @_max_vertex_textures > 0
197
- @_supports_bone_textures = @_supports_vertex_textures && false # TODO: extensions.get('OES_texture_float') ????
198
-
199
- #
200
-
201
- # TODO: get more shader precision formats ???
202
-
203
- # TODO: clear precision to maximum available ???
204
-
205
- # Plugins
206
-
207
- # TODO: when plugins are ready
208
- @shadow_map_plugin = ShadowMapPlugin.new(self, @lights, @_opengl_objects, @_opengl_objects_immediate)
209
- #
210
- # @sprite_plugin = SpritePlugin(self, @sprites)
211
- # @lens_flare_plugin = LensFlarePlugin(self, @lens_flares)
212
-
213
- # Events
214
-
215
- @on_object_removed = -> (event) {
216
- object = event.target
217
- object.traverse do |child|
218
- child.remove_event_listener(:remove, @on_object_removed)
219
- remove_child(child)
220
- end
221
- }
61
+ get_gpu_capabilities
222
62
 
223
- @on_geometry_dispose = -> (event) {
224
- geometry = event.target
225
- geometry.remove_event_listener(:dispose, @on_geometry_dispose)
226
- deallocate_geometry(geometry)
227
- }
63
+ init_plugins
64
+ end
228
65
 
229
- @on_texture_dispose = -> (event) {
230
- texture = event.target
231
- texture.remove_event_listener(:dispose, @on_texture_dispose)
232
- deallocate_texture(texture)
233
- @info[:memory][:textures] -= 1
234
- }
66
+ def supports_bone_textures?
67
+ @_supports_bone_textures
68
+ end
235
69
 
236
- @on_render_target_dispose = -> (event) {
237
- render_target = event.target
238
- render_target.remove_event_listener(:dispose, @on_render_target_dispose)
239
- deallocate_render_target(render_target)
240
- @info[:memory][:textures] -= 1
241
- }
70
+ def supports_vertex_textures?
71
+ @_supports_vertex_textures
72
+ end
242
73
 
243
- @on_material_dispose = -> (event) {
244
- material = event.target
245
- material.remove_event_listener(:dispose, @on_material_dispose)
246
- deallocate_material(material)
247
- }
74
+ def shadow_map_enabled?
75
+ @shadow_map_enabled
248
76
  end
249
77
 
250
78
  # TODO: get_context ???
@@ -268,13 +96,12 @@ module Mittsu
268
96
  end
269
97
 
270
98
  def set_viewport(x, y, width, height)
271
- @_viewport_x = x * pixel_ratio
272
- @_viewport_x = y * pixel_ratio
273
-
274
- @_viewport_width = width * pixel_ratio
275
- @_viewport_height = height * pixel_ratio
276
-
277
- glViewport(@_viewport_x, @_viewport_y, @_viewport_width, @_viewport_height)
99
+ default_target.set_and_use_viewport(
100
+ x * pixel_ratio,
101
+ y * pixel_ratio,
102
+ width * pixel_ratio,
103
+ height * pixel_ratio
104
+ )
278
105
  end
279
106
 
280
107
  def set_scissor(x, y, width, height)
@@ -290,6 +117,14 @@ module Mittsu
290
117
  enable ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST)
291
118
  end
292
119
 
120
+ def object_in_frustum?(object)
121
+ @_frustum.intersects_object?(object)
122
+ end
123
+
124
+ def sort_objects?
125
+ @sort_objects
126
+ end
127
+
293
128
  # clearing
294
129
 
295
130
  def get_clear_color
@@ -341,1946 +176,353 @@ module Mittsu
341
176
  @_current_geometry_program = ''
342
177
  @_current_material_id = -1
343
178
 
344
- @_lights_need_update = true
179
+ @light_renderer.reset
345
180
 
346
181
  @state.reset
347
182
  end
348
183
 
349
- def set_render_target(render_target = nil)
184
+ def set_render_target(render_target = default_target)
350
185
  # TODO: when OpenGLRenderTargetCube exists
351
- is_cube = false # render_target.is_a? OpenGLRenderTargetCube
186
+ # is_cube = render_target.is_a? OpenGLRenderTargetCube
352
187
 
353
- if render_target && render_target[:_opengl_framebuffer].nil?
354
- render_target.depth_buffer = true if render_target.depth_buffer.nil?
355
- render_target.stencil_buffer = true if render_target.stencil_buffer.nil?
188
+ render_target_impl = render_target.implementation(self)
356
189
 
357
- render_target.add_event_listener(:dispose, @on_render_target_dispose)
190
+ # TODO framebuffer logic for render target cube
191
+ render_target_impl.setup_buffers
358
192
 
359
- render_target[:_opengl_texture] = glCreateTexture
193
+ if render_target != @_current_render_target
194
+ render_target.use
195
+ @_current_render_target = render_target
196
+ end
197
+ end
360
198
 
361
- @info[:memory][:textures] += 1
199
+ def render(scene, camera, render_target = default_target, force_clear = false)
200
+ raise "ERROR: Mittsu::OpenGLRenderer#render: camera is not an instance of Mittsu::Camera" unless camera.is_a?(Camera)
362
201
 
363
- # Setup texture, create render and frame buffers
202
+ reset_cache_for_this_frame
364
203
 
365
- is_target_power_of_two = Math.power_of_two?(render_target.width) && Math.power_of_two?(render_target.height)
366
- gl_format = param_mittsu_to_gl(render_target.format)
367
- gl_type = param_mittsu_to_gl(render_target.type)
204
+ scene.update_matrix_world if scene.auto_update
205
+ camera.update_matrix_world if camera.parent.nil?
368
206
 
369
- if is_cube
370
- # TODO
371
- else
372
- render_target[:_opengl_framebuffer] = glCreateFramebuffer
207
+ update_skeleton_objects(scene)
373
208
 
374
- if render_target.share_depth_from
375
- render_target[:_opengl_renderbuffer] = render_target.share_depth_from[:_opengl_renderbuffer]
376
- else
377
- render_target[:_opengl_renderbuffer] = glCreateRenderbuffer
378
- end
209
+ update_screen_projection(camera)
210
+ scene.implementation(self).project
211
+ sort_objects_for_render if @sort_objects
379
212
 
380
- glBindTexture(GL_TEXTURE_2D, render_target[:_opengl_texture])
381
- set_texture_parameters(GL_TEXTURE_2D, render_target, is_target_power_of_two)
213
+ render_custom_plugins_pre_pass(scene, camera)
382
214
 
383
- glTexImage2D(GL_TEXTURE_2D, 0, gl_format, render_target.width, render_target.height, 0, gl_format, gl_type, nil)
215
+ set_matrices_for_immediate_objects(camera)
384
216
 
385
- setup_framebuffer(render_target[:_opengl_framebuffer], render_target, GL_TEXTURE_2D)
217
+ set_render_target(render_target)
218
+ perform_auto_clear if @auto_clear || force_clear
219
+ render_main_pass(scene, camera)
386
220
 
387
- if render_target.share_depth_from
388
- if render_target.depth_buffer && !render_target.stencil_buffer
389
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, render_target[:_opengl_renderbuffer])
390
- elsif render_target.depth_buffer && render_target.stencil_buffer
391
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, render_target[:_opengl_renderbuffer])
392
- end
393
- else
394
- setup_renderbuffer(render_target[:_opengl_renderbuffer], render_target)
395
- end
221
+ render_custom_plugins_post_pass(scene, camera)
396
222
 
397
- glGenerateMipmap(GL_TEXTURE_2D) if is_target_power_of_two
398
- end
223
+ render_target.implementation(self).update_mipmap
399
224
 
400
- # Release everything
225
+ ensure_depth_buffer_writing
226
+ end
401
227
 
402
- if is_cube
403
- # TODO
404
- else
405
- glBindTexture(GL_TEXTURE_2D, 0)
406
- end
228
+ def set_material_faces(material)
229
+ @state.set_double_sided(material.side == DoubleSide)
230
+ @state.set_flip_sided(material.side == BackSide)
231
+ end
407
232
 
408
- glBindRenderbuffer(GL_RENDERBUFFER, 0)
409
- glBindFramebuffer(GL_FRAMEBUFFER, 0)
410
- end
233
+ def render_buffer(camera, lights, fog, material, geometry_group, object)
234
+ return unless material.visible
411
235
 
412
- if render_target
413
- if is_cube
414
- # TODO
415
- else
416
- framebuffer = render_target[:_opengl_framebuffer]
417
- end
236
+ geometry_group.bind_vertex_array_object
418
237
 
419
- width = render_target.width
420
- height = render_target.height
238
+ update_object(object)
421
239
 
422
- vx = 0
423
- vy = 0
424
- else
425
- framebuffer = nil
240
+ program = set_program(camera, lights, fog, material, object)
241
+ attributes = program.attributes
242
+ buffers_need_update = switch_geometry_program(program, material, geometry_group)
426
243
 
427
- width = @_viewport_width
428
- height = @_viewport_height
244
+ @state.init_attributes if buffers_need_update
429
245
 
430
- vx = @_viewport_x
431
- vy = @_viewport_y
246
+ if !material.morph_targets && attributes['position'] && attributes['position'] >= 0
247
+ geometry_group.update_vertex_buffer(attributes['position']) if buffers_need_update
248
+ elsif object.morph_target_base
249
+ # TODO: when morphing is implemented
250
+ # setup_morph_targets(material, geometry_group, object)
432
251
  end
433
252
 
434
- if framebuffer != @_current_framebuffer
435
- glBindFramebuffer(GL_FRAMEBUFFER, framebuffer || 0)
436
- glViewport(vx, vy, width, height)
437
-
438
- @_current_framebuffer = framebuffer
253
+ if buffers_need_update
254
+ geometry_group.update_other_buffers(object, material, attributes)
439
255
  end
440
256
 
441
- @_current_width = width
442
- @_current_height = height
443
- end
257
+ @state.disable_unused_attributes
444
258
 
445
- def render(scene, camera, render_target = nil, force_clear = false)
446
- if !camera.is_a?(Camera)
447
- puts "ERROR: Mittsu::OpenGLRenderer#render: camera is not an instance of Mittsu::Camera"
448
- return
449
- end
259
+ object.implementation(self).render_buffer(camera, lights, fog, material, geometry_group, buffers_need_update)
450
260
 
451
- fog = scene.fog
261
+ # TODO: render particles
262
+ # when PointCloud
263
+ # glDrawArrays(GL_POINTS, 0, geometry_group.particle_count)
264
+ #
265
+ # @info[:render][:calls] += 1
266
+ # @info[:render][:points] += geometry_group.particle_count
267
+ end
452
268
 
453
- # reset caching for this frame
269
+ def compressed_texture_formats
270
+ # TODO: needs extensions.get ...
454
271
 
455
- @_current_geometry_program = ''
456
- @_current_material_id = -1
457
- @_current_camera = nil
458
- @_lights_need_update = true
272
+ @_compressed_texture_formats ||= []
273
+ end
459
274
 
460
- # update scene graph
461
- scene.update_matrix_world if scene.auto_update
275
+ # Events
462
276
 
463
- # update camera matrices and frustum
464
- camera.update_matrix_world if camera.parent.nil?
277
+ def on_object_removed(event)
278
+ object = event.target
279
+ object.traverse do |child|
280
+ child.remove_event_listener(:remove, method(:on_object_removed))
281
+ remove_child(child)
282
+ end
283
+ end
465
284
 
466
- # update skeleton objects
467
- # TODO: when SkinnedMesh is defined
468
- # scene.traverse do |object|
469
- # if object.is_a? SkinnedMesh
470
- # object.skeleton.update
471
- # end
472
- # end
285
+ def on_geometry_dispose(event)
286
+ geometry = event.target
287
+ geometry.remove_event_listener(:dispose, method(:on_geometry_dispose))
288
+ deallocate_geometry(geometry)
289
+ end
473
290
 
474
- camera.matrix_world_inverse.inverse(camera.matrix_world)
291
+ def on_texture_dispose(event)
292
+ texture = event.target
293
+ texture.remove_event_listener(:dispose, method(:on_texture_dispose))
294
+ deallocate_texture(texture)
295
+ @info[:memory][:textures] -= 1
296
+ end
475
297
 
476
- @_proj_screen_matrix.multiply_matrices(camera.projection_matrix, camera.matrix_world_inverse)
477
- @_frustum.set_from_matrix(@_proj_screen_matrix)
298
+ def on_render_target_dispose(event)
299
+ render_target = event.target
300
+ render_target.remove_event_listener(:dispose, method(:on_render_target_dispose))
301
+ deallocate_render_target(render_target)
302
+ @info[:memory][:textures] -= 1
303
+ end
478
304
 
479
- @lights.clear
480
- @opaque_objects.clear
481
- @transparent_objects.clear
305
+ def on_material_dispose(event)
306
+ material = event.target
307
+ material.remove_event_listener(:dispose, method(:on_material_dispose))
308
+ deallocate_material(material)
309
+ end
482
310
 
483
- @sprites.clear
484
- @lens_flares.clear
311
+ def create_implementation(thing)
312
+ OPENGL_IMPLEMENTATIONS[thing.class].new(thing, self)
313
+ end
485
314
 
486
- project_object(scene)
315
+ def clamp_to_max_size(image, max_size = @_max_texture_size)
316
+ width, height = image.width, image.height
317
+ if width > max_size || height > max_size
318
+ # TODO: scale the image ...
487
319
 
488
- if @sort_objects
489
- @opaque_objects.sort { |a,b| painter_sort_stable(a,b) }
490
- @transparent_objects.sort { |a,b| reverse_painter_sort_stable(a,b) }
320
+ puts "WARNING: Mittsu::OpenGLRenderer: image is too big (#{width} x #{height}). Resized to #{@_max_texture_size} x #{@_max_texture_size}"
491
321
  end
322
+ image
323
+ end
492
324
 
493
- # custom render plugins
494
- # TODO: when plugins are ready
495
- @shadow_map_plugin.render(scene, camera)
496
-
497
- #
325
+ def add_opengl_object(buffer, object)
326
+ add_buffer(@_opengl_objects, buffer, object)
327
+ end
498
328
 
499
- @info[:render][:calls] = 0
500
- @info[:render][:vertices] = 0
501
- @info[:render][:faces] = 0
502
- @info[:render][:points] = 0
329
+ def remove_opengl_object(object)
330
+ @_opengl_objects.delete(object.id)
331
+ end
503
332
 
504
- set_render_target(render_target)
333
+ private
505
334
 
506
- if @auto_clear || force_clear
507
- clear(@auto_clear_color, @auto_clear_depth, @auto_clear_stencil)
335
+ def clear_color(r, g, b, a)
336
+ if (@_premultiplied_alpha)
337
+ r *= a; g *= a; b *= a
508
338
  end
509
339
 
510
- # set matrices for immediate objects
511
-
512
- @_opengl_objects_immediate.each do |opengl_object|
513
- object = opengl_object[:object]
514
-
515
- if object.visible
516
- setup_matrices(object, camera)
517
- unroll_immediate_buffer_material(opengl_object)
518
- end
519
- end
340
+ glClearColor(r, g, b, a)
341
+ end
520
342
 
521
- if scene.override_material
522
- override_material = scene.override_material
343
+ def set_default_gl_state
344
+ glClearColor(0.0, 0.0, 0.0, 1.0)
345
+ glClearDepth(1)
346
+ glClearStencil(0)
523
347
 
524
- set_material(override_material)
348
+ glEnable(GL_DEPTH_TEST)
349
+ glDepthFunc(GL_LEQUAL)
525
350
 
526
- render_objects(opaque_object, camera, @lights, fog, override_material)
527
- render_objects(transparent_objects, camera, @lights, fog, override_material)
528
- render_objects_immediate(@_opengl_objects_immediate, nil, camera, @lights, fog, override_material)
529
- else
530
- # opaque pass (front-to-back order)
351
+ glFrontFace(GL_CCW)
352
+ glCullFace(GL_BACK)
353
+ glEnable(GL_CULL_FACE)
531
354
 
532
- @state.set_blending(NoBlending)
355
+ glEnable(GL_BLEND)
356
+ glBlendEquation(GL_FUNC_ADD)
357
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
533
358
 
534
- render_objects(@opaque_objects, camera, @lights, fog, nil)
535
- render_objects_immediate(@_opengl_objects_immediate, :opaque, camera, @lights, fog, nil)
359
+ default_target.use_viewport
536
360
 
537
- # transparent pass (back-to-front-order)
361
+ clear_color(@_clear_color.r, @_clear_color.g, @_clear_color.b, @_clear_alpha)
362
+ end
538
363
 
539
- render_objects(@transparent_objects, camera, @lights, fog, nil)
540
- render_objects_immediate(@_opengl_objects_immediate, :transparent, camera, @lights, fog, nil)
541
- end
364
+ def render_objects(render_list, camera, lights, fog, override_material)
365
+ material = nil
366
+ render_list.each do |opengl_object|
367
+ object = opengl_object.object
368
+ buffer = opengl_object.buffer
542
369
 
543
- # custom render plugins (post pass)
370
+ object.implementation(self).setup_matrices(camera)
544
371
 
545
- # TODO: when plugins are ready
546
- # @sprite_plugin.render(scene, camera)
547
- # lens_flare_plugin.render(scene, camera, @_current_width, @_current_height)
372
+ if override_material
373
+ material = override_material
374
+ material_impl = material.implementation(self)
375
+ else
376
+ material = opengl_object.material
377
+ next unless material
378
+ material_impl = material.implementation(self)
379
+ material_impl.set
380
+ end
548
381
 
549
- # generate mipmap if we're using any kind of mipmap filtering
550
- if render_target && render_target.generate_mipmaps && render_target.min_filter != NearestFilter && render_target.min_filter != LinearFilter
551
- update_render_target_mipmap(render_target)
382
+ set_material_faces(material)
383
+ if buffer.is_a? BufferGeometry
384
+ # TODO
385
+ # render_buffer_direct(camera, lights, fog, material, buffer, object)
386
+ else
387
+ render_buffer(camera, lights, fog, material, buffer.implementation(self), object)
388
+ end
552
389
  end
390
+ end
553
391
 
554
- # endure depth buffer writing is enabled so it can be cleared on next render
555
- @state.set_depth_test(true)
556
- @state.set_depth_write(true)
557
- @state.set_color_write(true)
558
-
559
- #glFinish ??????
560
- end
561
-
562
- def set_material_faces(material)
563
- @state.set_double_sided(material.side == DoubleSide)
564
- @state.set_flip_sided(material.side == BackSide)
565
- end
566
-
567
- def render_buffer(camera, lights, fog, material, geometry_group, object)
568
- return unless material.visible
569
-
570
- # TODO: place to put this ???
571
- vertex_array = geometry_group[:_opengl_vertex_array]
572
- if vertex_array
573
- glBindVertexArray(vertex_array)
574
- end
575
-
576
- update_object(object)
577
-
578
- program = set_program(camera, lights, fog, material, object)
579
-
580
- attributes = program.attributes
581
-
582
- update_buffers = false
583
- wireframe_bit = material.wireframe ? 1 : 0
584
- geometry_program = "#{geometry_group[:id]}_#{program.id}_#{wireframe_bit}"
585
-
586
- if geometry_program != @_current_geometry_program
587
- @_current_geometry_program = geometry_program
588
- update_buffers = true
589
- end
590
-
591
- @state.init_attributes if update_buffers
592
-
593
- # vertices
594
- if !material.morph_targets && attributes['position'] && attributes['position'] >= 0
595
- if update_buffers
596
- glBindBuffer(GL_ARRAY_BUFFER, geometry_group[:_opengl_vertex_buffer])
597
-
598
- @state.enable_attribute(attributes['position'])
599
-
600
- glVertexAttribPointer(attributes['position'], 3, GL_FLOAT, GL_FALSE, 0, 0)
601
- end
602
- elsif object.morph_target_base
603
- setup_morph_targets(material, geometry_group, object)
604
- end
605
-
606
- if update_buffers
607
- # custom attributes
608
-
609
- # use the per-geometry_group custom attribute arrays which are setup in init_mesh_buffers
610
-
611
- if geometry_group[:_opengl_custom_attributes_list]
612
- geometry_group[:_opengl_custom_attributes_list].each do |attribute|
613
- if attributes[attribute.buffer.belongs_to_attribute] >= 0
614
- glBindBuffer(GL_ARRAY_BUFFER, attribute.buffer)
615
-
616
- @state.enable_attribute(attributes[attribute.buffer.belongs_to_attribute])
617
-
618
- glVertexAttribPointer(attributes[attribute.buffer.belongs_to_attribute], attribute.size, GL_FLOAT, GL_FALSE, 0, 0)
619
- end
620
- end
621
- end
622
-
623
- # colors
624
-
625
- if attributes['color'] && attributes['color'] >= 0
626
- glBindBuffer(GL_ARRAY_BUFFER, geometry_group[:_opengl_color_buffer])
627
-
628
- @state.enable_attribute(attributes['color'])
629
-
630
- glVertexAttribPointer(attributes['color'], 3, GL_FLOAT, GL_FALSE, 0, 0)
631
- elsif !material.default_attribute_values.nil?
632
- glVertexAttrib3fv(attributes['color'], material.default_attribute_values.color)
633
- end
634
-
635
- # normals
636
-
637
- if attributes['normal'] && attributes['normal'] >= 0
638
- glBindBuffer(GL_ARRAY_BUFFER, geometry_group[:_opengl_normal_buffer])
639
-
640
- @state.enable_attribute(attributes['normal'])
641
-
642
- glVertexAttribPointer(attributes['normal'], 3, GL_FLOAT, GL_FALSE, 0, 0)
643
- end
644
-
645
- # tangents
646
-
647
- if attributes['tangent'] && attributes['tangent'] >= 0
648
- glBindBuffer(GL_ARRAY_BUFFER, geometry_group[:_opengl_tangent_buffer])
649
-
650
- @state.enable_attribute(attributes['tangent'])
651
-
652
- glVertexAttribPointer(attributes['tangent'], 4, GL_FLOAT, GL_FALSE, 0, 0)
653
- end
654
-
655
- # uvs
656
-
657
- if attributes['uv'] && attributes['uv'] >= 0
658
- if object.geometry.face_vertex_uvs[0]
659
- glBindBuffer(GL_ARRAY_BUFFER, geometry_group[:_opengl_uv_buffer])
660
-
661
- @state.enable_attribute(attributes['uv'])
662
-
663
- glVertexAttribPointer(attributes['uv'], 2, GL_FLOAT, GL_FALSE, 0, 0)
664
- elsif !material.default_attribute_values.nil?
665
- glVertexAttrib2fv(attributes['uv'], material.default_attribute_values.uv)
666
- end
667
- end
668
-
669
- if attributes['uv2'] && attributes['uv2'] >= 0
670
- if object.geometry.face_vertex_uvs[1]
671
- glBindBuffer(GL_ARRAY_BUFFER, geometry_group[:_opengl_uv2_buffer])
672
-
673
- @state.enable_attribute(attributes['uv2'])
674
-
675
- glVertexAttribPointer(attributes['uv2'], 2, GL_FLOAT, GL_FALSE, 0, 0)
676
- elsif !material.default_attribute_values.nil?
677
- glVertexAttrib2fv(attributes['uv2'], material.default_attribute_values.uv2)
678
- end
679
- end
680
-
681
- if material.skinning && attributes['skin_index'] && attributes['skin_weight'] && attributes['skin_index'] >= 0 && attributes['skin_weight'] >= 0
682
- glBindBuffer(GL_ARRAY_BUFFER, geometry_group[:_opengl_skin_indices_buffer])
683
-
684
- @state.enable_attribute(attributes['skin_index'])
685
-
686
- glVertexAttribPointer(attributes['skin_index'], 4, GL_FLOAT, GL_FALSE, 0, 0)
687
-
688
- glBindBuffer(GL_ARRAY_BUFFER, geometry_group[:_opengl_skin_weight_buffer])
689
-
690
- @state.enable_attribute(attributes['skin_weight'])
691
-
692
- glVertexAttribPointer(attributes['skin_weight'], 4, GL_FLOAT, GL_FALSE, 0, 0)
693
- end
694
-
695
- # line distances
696
-
697
- if attributes['line_distances'] && attributes['line_distances'] >= 0
698
- glBindBuffer(GL_ARRAY_BUFFER, geometry_group[:_opengl_line_distance_buffer])
699
-
700
- @state.enable_attribute(attributes['line_distance'])
701
-
702
- glVertexAttribPointer(attributes['line_distance'], 1, GL_FLOAT, GL_FALSE, 0, 0)
703
- end
704
- end
705
-
706
- @state.disable_unused_attributes
707
-
708
- case object
709
-
710
- # render mesh
711
- when Mesh
712
- type = GL_UNSIGNED_INT # geometry_group[:_type_array] == Uint32Array ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT
713
-
714
- # wireframe
715
- if material.wireframe
716
- @state.set_line_width(material.wireframe_linewidth * @pixel_ratio)
717
-
718
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometry_group[:_opengl_line_buffer]) if update_buffers
719
- glDrawElements(GL_LINES, geometry_group[:_opengl_line_count], type, 0)
720
-
721
- # triangles
722
- else
723
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometry_group[:_opengl_face_buffer]) if update_buffers
724
- glDrawElements(GL_TRIANGLES, geometry_group[:_opengl_face_count], type, 0)
725
- end
726
-
727
- @info[:render][:calls] += 1
728
- @info[:render][:vertices] += geometry_group[:_opengl_face_count]
729
- @info[:render][:faces] += geometry_group[:_opengl_face_count] / 3
730
- when Line
731
- mode = object.mode == LineStrip ? GL_LINE_STRIP : GL_LINES
732
-
733
- @state.set_line_width(material.line_width * @pixel_ratio)
734
-
735
- glDrawArrays(mode, 0, geometry_group[:_opengl_line_count])
736
-
737
- @info[:render][:calls] += 1
738
-
739
- # TODO: render particles
740
- # when PointCloud
741
- # glDrawArrays(GL_POINTS, 0, geometry_group[:_opengl_particle_count])
742
- #
743
- # @info[:render][:calls] += 1
744
- # @info[:render][:points] += geometry_group[:_opengl_particle_count]
745
- end
746
- end
747
-
748
- def set_texture(texture, slot)
749
- glActiveTexture(GL_TEXTURE0 + slot)
750
-
751
- if texture.needs_update?
752
- upload_texture(texture)
753
- else
754
- glBindTexture(GL_TEXTURE_2D, texture[:_opengl_texture])
755
- end
756
- end
757
-
758
- def upload_texture(texture)
759
- if texture[:_opengl_init].nil?
760
- texture[:_opengl_init] = true
761
- texture.add_event_listener :dispose, @on_texture_dispose
762
- texture[:_opengl_texture] = glCreateTexture
763
- @info[:memory][:textures] += 1
764
- end
765
-
766
- glBindTexture(GL_TEXTURE_2D, texture[:_opengl_texture])
767
-
768
- # glPixelStorei(GL_UNPACK_FLIP_Y_WEBGL, texture.flip_y) ???
769
- # glPixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiply_alpha) ???
770
- glPixelStorei(GL_UNPACK_ALIGNMENT, texture.unpack_alignment)
771
-
772
- texture.image = clamp_to_max_size(texture.image, @_max_texture_size)
773
-
774
- image = texture.image
775
- is_image_power_of_two = Math.power_of_two?(image.width) && Math.power_of_two?(image.height)
776
- gl_format = param_mittsu_to_gl(texture.format)
777
- gl_type = param_mittsu_to_gl(texture.type)
778
-
779
- set_texture_parameters(GL_TEXTURE_2D, texture, is_image_power_of_two)
780
-
781
- mipmaps = texture.mipmaps
782
-
783
- if texture.is_a?(DataTexture)
784
- # use manually created mipmaps if available
785
- # if there are no manual mipmaps
786
- # set 0 level mipmap and then use GL to generate other mipmap levels
787
-
788
- if !mipmaps.empty? && is_image_power_of_two
789
- mipmaps.each_with_index do |mipmap, i|
790
- glTexImage2D(GL_TEXTURE_2D, i, gl_format, mipmap.width, mipmap.height, 0, gl_format, gl_type, mipmap.data)
791
- end
792
- else
793
- glTexImage2D(GL_TEXTURE_2D, 0, gl_format, image.width, image.height, 0, gl_format, gl_type, image.data)
794
- end
795
- elsif texture.is_a?(CompressedTexture)
796
- mipmaps.each_with_index do |mipmap, i|
797
- if texture.format != RGBAFormat && texture.format != RGBFormat
798
- if get_compressed_texture_formats.index(gl_format)
799
- glCompressedTexImage2D(GL_TEXTURE_2D, i, gl_format, mipmap.width, mipmap.height, 0, mipmap.data)
800
- else
801
- puts 'WARNING: Mittsu::OpenGLRenderer: Attempt to load unsupported compressed texture format in #upload_texture'
802
- end
803
- else
804
- glTexImage2D(GL_TEXTURE_2D, i, gl_format, mipmap.width, mipmap.height, 0, gl_format, gl_type, mipmap.data)
805
- end
806
- end
807
- else # regular texture (image, video, canvas)
808
- # use manually created mipmaps if available
809
- # if there are no manual mipmaps
810
- # set 0 level mipmap and then use GL to generate other mipmap levels
811
-
812
- if !mipmaps.empty? && is_image_power_of_two
813
- mipmaps.each_with_index do |mipmap, i|
814
- glTexImage2D(GL_TEXTURE_2D, i, gl_format, mipmap.width, mipmap.height, 0, gl_format, gl_type, mipmap.data)
815
- end
816
-
817
- texture.generate_mipmaps = false
818
- else
819
- glTexImage2D(GL_TEXTURE_2D, 0, gl_format, texture.image.width, texture.image.height, 0, gl_format, gl_type, texture.image.data)
820
- end
821
- end
822
-
823
- if texture.generate_mipmaps && is_image_power_of_two
824
- glGenerateMipmap(GL_TEXTURE_2D)
825
- end
826
-
827
- texture.needs_update = false
828
-
829
- if texture.on_update
830
- texture.on_update.()
831
- end
832
- end
833
-
834
- private
835
-
836
- def clear_color(r, g, b, a)
837
- if (@_premultiplied_alpha)
838
- r *= a; g *= a; b *= a
839
- end
840
-
841
- glClearColor(r, g, b, a)
842
- end
843
-
844
- def set_default_gl_state
845
- glClearColor(0.0, 0.0, 0.0, 1.0)
846
- glClearDepth(1)
847
- glClearStencil(0)
848
-
849
- glEnable(GL_DEPTH_TEST)
850
- glDepthFunc(GL_LEQUAL)
851
-
852
- glFrontFace(GL_CCW)
853
- glCullFace(GL_BACK)
854
- glEnable(GL_CULL_FACE)
855
-
856
- glEnable(GL_BLEND)
857
- glBlendEquation(GL_FUNC_ADD)
858
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
859
-
860
- glViewport(@_viewport_x, @_viewport_y, @_viewport_width, @_viewport_height)
861
-
862
- clear_color(@_clear_color.r, @_clear_color.g, @_clear_color.b, @_clear_alpha)
863
- end
864
-
865
- def get_compressed_texture_formats
866
- return @_compressed_texture_formats ||= []
867
- # TODO: needs extensions.get ...
868
- end
869
-
870
- def painter_sort_stable(a, b)
871
- if a[:object].render_order != b[:object].render_order
872
- a[:object].render_order - b[:object].render_order
873
- elsif a[:material].id != b[:material].id
874
- a[:material].id - b[:material].id
875
- elsif a[:z] != b[:z]
876
- a[:z] - b[:z]
877
- else
878
- a[:id] - b[:id]
879
- end
880
- end
881
-
882
- def reverse_painter_sort_stable(a, b)
883
- if a.object.render_order != b.object.render_order
884
- a.object.render_order - b.object.render_order
885
- elsif a.z != b.z
886
- b.z - a.z
887
- else
888
- a.id - b.id
889
- end
890
- end
891
-
892
- def get_gl_parameter(pname)
893
- data = ' '
894
- glGetIntegerv(pname, data)
895
- data.unpack('L')[0]
896
- end
897
-
898
- def project_object(object)
899
- return unless object.visible
900
- if object.is_a? Scene # || object.is_a? Group # TODO: when Group is defined
901
- # skip
902
- else
903
- init_object(object)
904
- if object.is_a? Light
905
- @lights << object
906
- # if object.is_a? Sprite # TODO
907
- # @sprites << object
908
- # if object.is_a? LensFlare # TODO
909
- # @lens_flares << object
910
- else
911
- opengl_objects = @_opengl_objects[object.id]
912
- if opengl_objects && (!object.frustum_culled || @_frustum.intersects_object?(object))
913
- opengl_objects.each do |opengl_object|
914
- unroll_buffer_material(opengl_object)
915
- opengl_object[:render] = true
916
- if @sort_objects
917
- @_vector3.set_from_matrix_position(object.matrix_world)
918
- @_vector3.apply_projection(@_proj_screen_matrix)
919
-
920
- opengl_object[:z] = @_vector3.z
921
- end
922
- end
923
- end
924
- end
925
- end
926
-
927
- object.children.each do |child|
928
- project_object(child)
929
- end
930
- end
931
-
932
- def render_objects(render_list, camera, lights, fog, override_material)
933
- material = nil
934
- render_list.each do |opengl_object|
935
- object = opengl_object[:object]
936
- buffer = opengl_object[:buffer]
937
-
938
- setup_matrices(object, camera)
939
-
940
- if override_material
941
- material = override_material
942
- else
943
- material = opengl_object[:material]
944
- next unless material
945
- set_material(material)
946
- end
947
-
948
- set_material_faces(material)
949
- if buffer.is_a? BufferGeometry
950
- render_buffer_direct(camera, lights, fog, material, buffer, object)
951
- else
952
- render_buffer(camera, lights, fog, material, buffer, object)
953
- end
954
- end
955
- end
956
-
957
- def render_objects_immediate(render_list, material_type, camera, lights, fog, override_material)
958
- material = nil
959
- render_list.each do |opengl_object|
960
- object = opengl_object[:object]
961
- if object.visible
962
- if override_material
963
- material = override_material
964
- else
965
- material = opengl_object[material_type]
966
- next unless material
967
- set_material(material)
968
- end
969
- render_immediate_object(camera, lights, fog, material, object)
970
- end
971
- end
972
- end
973
-
974
- def init_object(object)
975
- if object[:_opengl_init].nil?
976
- object[:_opengl_init] = true
977
- object[:_model_view_matrix] = Matrix4.new
978
- object[:_normal_matrix] = Matrix3.new
979
-
980
- object.add_event_listener(:removed, @on_object_removed)
981
- end
982
-
983
- geometry = object.geometry
984
-
985
- if geometry.nil?
986
- # ImmediateRenderObject
987
- elsif geometry[:_opengl_init].nil?
988
- geometry[:_opengl_init] = true
989
- geometry.add_event_listener(:dispose, @on_geometry_dispose)
990
- case object
991
- when BufferGeometry
992
- @info[:memory][:geometries] += 1
993
- when Mesh
994
- init_geometry_groups(object, geometry)
995
- when Line
996
- if geometry[:_opengl_vertex_buffer].nil?
997
- create_line_buffers(geometry)
998
- init_line_buffers(geometry, object)
999
-
1000
- geometry.vertices_need_update = true
1001
- geometry.colors_need_update = true
1002
- geometry.line_distances_need_update
1003
- end
1004
- # TODO: when PointCloud exists
1005
- # when PointCloud
1006
- # if geometry[:_opengl_vertex_buffer].nil?
1007
- # create_particle_buffers(geometry)
1008
- # init_particle_buffers(geometry, object)
1009
- #
1010
- # geometry.vertices_need_update = true
1011
- # geometry.colors_need_update = true
1012
- # end
1013
- end
1014
- end
1015
-
1016
- if object[:_opengl_active].nil?
1017
- object[:_opengl_active] = true
1018
- case object
1019
- when Mesh
1020
- case geometry
1021
- when BufferGeometry
1022
- add_buffer(@_opengl_objects, geometry, object)
1023
- when Geometry
1024
- geometry_groups_list = @geometry_groups[geometry.id]
1025
- geometry_groups_list.each do |group|
1026
- add_buffer(@_opengl_objects, group, object)
1027
- end
1028
- end
1029
- when Line #, PointCloud TODO
1030
- add_buffer(@_opengl_objects, geometry, object)
1031
- else
1032
- # TODO: when ImmediateRenderObject exists
1033
- # if object.is_a? ImmediateRenderObject || object.immediate_render_callback
1034
- # add_buffer_immediate(@_opengl_objects_immediate, object)
1035
- # end
1036
- end
1037
- end
1038
- end
1039
-
1040
- def make_groups(geometry, uses_face_material = false)
1041
- max_vertices_in_group = 65535 # TODO: OES_element_index_uint ???
1042
-
1043
- hash_map = {}
1044
-
1045
- num_morph_targets = geometry.morph_targets.length
1046
- num_morph_normals = geometry.morph_normals.length
1047
-
1048
- groups = {}
1049
- groups_list = []
1050
-
1051
- geometry.faces.each_with_index do |face, f|
1052
- material_index = uses_face_material ? face.material_index : 0
1053
-
1054
- if !hash_map.include? material_index
1055
- hash_map[material_index] = { hash: material_index, counter: 0 }
1056
- end
1057
-
1058
- group_hash = "#{hash_map[material_index][:hash]}_#{hash_map[material_index][:counter]}"
1059
-
1060
- if !groups.include? group_hash
1061
- group = {
1062
- id: @geometry_group_counter += 1,
1063
- faces3: [],
1064
- material_index: material_index,
1065
- vertices: 0,
1066
- num_morph_targets: num_morph_targets,
1067
- num_morph_normals: num_morph_normals
1068
- }
1069
-
1070
- groups[group_hash] = group
1071
- groups_list << group
1072
- end
1073
-
1074
- if groups[group_hash][:vertices] + 3 > max_vertices_in_group
1075
- hash_map[material_index][:counter] += 1
1076
- group_hash = "#{hash_map[material_index][:hash]}_#{hash_map[material_index][:counter]}"
1077
-
1078
- if !groups.include? group_hash
1079
- group = {
1080
- id: @geometry_group_counter += 1,
1081
- faces3: [],
1082
- material_index: material_index,
1083
- vertices: 0,
1084
- num_morph_targets: num_morph_targets,
1085
- num_morph_normals: num_morph_normals
1086
- }
1087
-
1088
- groups[group_hash] = group
1089
- groups_list << group
1090
- end
1091
- end
1092
- groups[group_hash][:faces3] << f
1093
- groups[group_hash][:vertices] += 3
1094
- end
1095
- groups_list
1096
- end
1097
-
1098
- def init_geometry_groups(object, geometry)
1099
- # material = object.material
1100
- add_buffers = false
1101
-
1102
- if @geometry_groups[geometry.id].nil? || geometry.groups_need_update
1103
- @_opengl_objects.delete object.id
1104
-
1105
- @geometry_groups[geometry.id] = make_groups(geometry, false) # TODO: material.is_a?(MeshFaceMaterial))
1106
-
1107
- geometry.groups_need_update = false
1108
- end
1109
-
1110
- geometry_groups_list = @geometry_groups[geometry.id]
1111
-
1112
- # create separate VBOs per geometry chunk
1113
-
1114
- geometry_groups_list.each do |geometry_group|
1115
- # initialize VBO on the first access
1116
- if geometry_group[:_opengl_vertex_buffer].nil?
1117
- create_mesh_buffers(geometry_group)
1118
- init_mesh_buffers(geometry_group, object)
1119
-
1120
- geometry.vertices_need_update = true
1121
- geometry.morph_targets_need_update = true
1122
- geometry.elements_need_update = true
1123
- geometry.uvs_need_update = true
1124
- geometry.normals_need_update = true
1125
- geometry.tangents_need_update = true
1126
- geometry.colors_need_update = true
1127
- else
1128
- add_buffers = false
1129
- end
1130
-
1131
- if add_buffers || object[:_opengl_active].nil?
1132
- add_buffer(@_opengl_objects, geometry_group, object)
1133
- end
1134
- end
1135
-
1136
- object[:_opengl_active] = true
1137
- end
1138
-
1139
- def add_buffer(objlist, buffer, object)
1140
- id = object.id
1141
- objlist[id] ||= []
1142
- objlist[id] << {
1143
- id: id,
1144
- buffer: buffer,
1145
- object: object,
1146
- material: nil,
1147
- z: 0
1148
- }
1149
- end
1150
-
1151
- def unroll_buffer_material(globject)
1152
- object = globject[:object]
1153
- # buffer = globject[:buffer]
1154
-
1155
- # geometry = object.geometry
1156
- material = object.material
1157
-
1158
- if material
1159
- # TODO: when MeshFaceMaterial exists
1160
- # if material.is_a? MeshFaceMaterial
1161
- # material_index = geometry.is_a? BufferGeometry ? 0 : buffer.material_index
1162
- #
1163
- # material = material.materials[material_index]
1164
- # end
1165
- globject[:material] = material
1166
-
1167
- if material.transparent
1168
- @transparent_objects << globject
1169
- else
1170
- @opaque_objects << globject
1171
- end
1172
- end
1173
- end
1174
-
1175
- def setup_matrices(object, camera)
1176
- object[:_model_view_matrix].tap do |model_view_matrix|
1177
- model_view_matrix.multiply_matrices(camera.matrix_world_inverse, object.matrix_world)
1178
- object[:_normal_matrix].normal_matrix(model_view_matrix)
1179
- end
1180
- end
1181
-
1182
- def set_material(material)
1183
- if material.transparent
1184
- @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)
1185
- else
1186
- @state.set_blending(NoBlending)
1187
- end
1188
-
1189
- @state.set_depth_test(material.depth_test)
1190
- @state.set_depth_write(material.depth_write)
1191
- @state.set_color_write(material.color_write)
1192
- @state.set_polygon_offset(material.polygon_offset, material.polygon_offset_factor, material.polygon_offset_units)
1193
- end
1194
-
1195
- def create_line_buffers(geometry)
1196
- geometry[:_opengl_vertex_array] = glCreateVertexArray
1197
-
1198
- geometry[:_opengl_vertex_buffer] = glCreateBuffer
1199
- geometry[:_opengl_color_buffer] = glCreateBuffer
1200
- geometry[:_opengl_line_distance_buffer] = glCreateBuffer
1201
-
1202
- @info[:memory][:geometries] += 1
1203
- end
1204
-
1205
- def create_mesh_buffers(geometry_group)
1206
- geometry_group[:_opengl_vertex_array] = glCreateVertexArray
1207
-
1208
- geometry_group[:_opengl_vertex_buffer] = glCreateBuffer
1209
- geometry_group[:_opengl_normal_buffer] = glCreateBuffer
1210
- geometry_group[:_opengl_tangent_buffer] = glCreateBuffer
1211
- geometry_group[:_opengl_color_buffer] = glCreateBuffer
1212
- geometry_group[:_opengl_uv_buffer] = glCreateBuffer
1213
- geometry_group[:_opengl_uv2_buffer] = glCreateBuffer
1214
-
1215
- geometry_group[:_opengl_skin_indices_buffer] = glCreateBuffer
1216
- geometry_group[:_opengl_skin_weights_buffer] = glCreateBuffer
1217
-
1218
- geometry_group[:_opengl_face_buffer] = glCreateBuffer
1219
- geometry_group[:_opengl_line_buffer] = glCreateBuffer
1220
-
1221
- num_morph_targets = geometry_group[:num_morph_targets]
1222
-
1223
- if num_morph_targets
1224
- geometry_group[:_opengl_morph_targets_buffers] = []
1225
-
1226
- num_morph_targets.times do |m|
1227
- geometry_group[:_opengl_morph_targets_buffers] << glCreateBuffer
1228
- end
1229
- end
1230
-
1231
- num_morph_normals = geometry_group[:num_morph_normals]
1232
-
1233
- if num_morph_normals
1234
- geometry_group[:_opengl_morph_normals_buffers] = []
1235
-
1236
- num_morph_normals.times do |m|
1237
- geometry_group[:_opengl_morph_normals_buffers] << glCreateBuffer
1238
- end
1239
- end
1240
-
1241
- @info[:memory][:geometries] += 1
1242
- end
1243
-
1244
- def glCreateBuffer
1245
- @_b ||= ' '*8
1246
- glGenBuffers(1, @_b)
1247
- @_b.unpack('L')[0]
1248
- end
1249
-
1250
- def glCreateTexture
1251
- @_b ||= ' '*8
1252
- glGenTextures(1, @_b)
1253
- @_b.unpack('L')[0]
1254
- end
1255
-
1256
- def glCreateVertexArray
1257
- @_b ||= ' '*8
1258
- glGenVertexArrays(1, @_b)
1259
- @_b.unpack('L')[0]
1260
- end
1261
-
1262
- def glCreateFramebuffer
1263
- @_b ||= ' '*8
1264
- glGenFramebuffers(1, @_b)
1265
- @_b.unpack('L')[0]
1266
- end
1267
-
1268
- def glCreateRenderbuffer
1269
- @_b ||= ' '*8
1270
- glGenRenderbuffers(1, @_b)
1271
- @_b.unpack('L')[0]
1272
- end
1273
-
1274
- def array_to_ptr_easy(data)
1275
- size_of_element = data.first.is_a?(Float) ? Fiddle::SIZEOF_FLOAT : Fiddle::SIZEOF_INT
1276
- if data.first.is_a?(Float)
1277
- size_of_element = Fiddle::SIZEOF_FLOAT
1278
- format_of_element = 'F'
1279
- # data.map!{ |d| d.nil? ? 0.0 : d }
1280
- else
1281
- size_of_element = Fiddle::SIZEOF_INT
1282
- format_of_element = 'L'
1283
- # data.map!{ |d| d.nil? ? 0 : d }
1284
- end
1285
- size = data.length * size_of_element
1286
- array_to_ptr(data, size, format_of_element)
1287
- end
1288
-
1289
- def array_to_ptr(data, size, format)
1290
- ptr = Fiddle::Pointer.malloc(size)
1291
- ptr[0,size] = data.pack(format * data.length)
1292
- ptr
1293
- end
1294
-
1295
- def glBufferData_easy(target, data, usage)
1296
- ptr = array_to_ptr_easy(data)
1297
- glBufferData(target, ptr.size, ptr, usage)
1298
- end
1299
-
1300
- def init_custom_attributes(object)
1301
- geometry = object.geometry
1302
- material = object.material
1303
-
1304
- nvertices = geometry.vertices.length
1305
-
1306
- if material.attributes
1307
- geometry[:_opengl_custom_attributes_list] ||= []
1308
-
1309
- material.attributes.each do |(name, attribute)|
1310
- if !attribute[:_opengl_initialized] || attribute.create_unique_buffers
1311
- attribute[:_opengl_initialized] = true
1312
-
1313
- size = case attribute.type
1314
- when :v2 then 2
1315
- when :v3 then 3
1316
- when :v4 then 4
1317
- when :c then 3
1318
- else 1
1319
- end
1320
-
1321
- attribute.size = size
1322
-
1323
- attribute.array = Array.new(nvertices * size) # Float32Array
1324
-
1325
- attribute.buffer = glCreateBuffer
1326
- attribute.buffer.belongs_to_attribute = name
1327
-
1328
- attribute.needs_update = true
1329
- end
1330
-
1331
- geometry[:_opengl_custom_attributes_list] << attribute
1332
- end
1333
- end
1334
- end
1335
-
1336
- def init_line_buffers(geometry, object)
1337
- nvertices = geometry.vertices.length
1338
-
1339
- geometry[:_vertex_array] = Array.new(nvertices * 3, 0.0) # Float32Array
1340
- geometry[:_color_array] = Array.new(nvertices * 3, 0.0) # Float32Array
1341
- geometry[:_line_distance_array] = Array.new(nvertices, 0.0) # Float32Array
1342
-
1343
- geometry[:_opengl_line_count] = nvertices
1344
-
1345
- init_custom_attributes(object)
1346
- end
1347
-
1348
- def init_mesh_buffers(geometry_group, object)
1349
- geometry = object.geometry
1350
- faces3 = geometry_group[:faces3]
1351
-
1352
- nvertices = faces3.length * 3
1353
- ntris = faces3.length * 1
1354
- nlines = faces3.length * 3
1355
-
1356
- material = get_buffer_material(object, geometry_group)
1357
-
1358
- geometry_group[:_vertex_array] = Array.new(nvertices * 3) # Float32Array
1359
- geometry_group[:_normal_array] = Array.new(nvertices * 3) # Float32Array
1360
- geometry_group[:_color_array] = Array.new(nvertices * 3) # Float32Array
1361
- geometry_group[:_uv_array] = Array.new(nvertices * 2) # Float32Array
1362
-
1363
- if geometry.face_vertex_uvs.length > 1
1364
- geometry_group[:_uv2_array] = Array.new(nvertices * 2) # Float32Array
1365
- end
1366
-
1367
- if geometry.has_tangents
1368
- geometry_group[:_tangent_array] = Array.new(nvertices * 4) # Float32Array
1369
- end
1370
-
1371
- if !object.geometry.skin_weights.empty? && !object.geometry.skin_indices.empty?
1372
- geometry_group[:_skin_index_array] = Array.new(nvertices * 4) # Float32Array
1373
- geometry_group[:_skin_weight_array] = Array.new(nvertices * 4)
1374
- end
1375
-
1376
- # UintArray from OES_element_index_uint ???
1377
-
1378
- geometry_group[:_type_array] = Array # UintArray ???
1379
- geometry_group[:_face_array] = Array.new(ntris * 3)
1380
- geometry_group[:_line_array] = Array.new(nlines * 2)
1381
-
1382
- num_morph_targets = geometry_group[:num_morph_targets]
1383
-
1384
- if !num_morph_targets.zero?
1385
- geometry_group[:_morph_targets_arrays] = []
1386
-
1387
- num_morph_targets.times do |m|
1388
- geometry_group[:_morph_targets_arrays] << Array.new(nvertices * 3) # Float32Array ???
1389
- end
1390
- end
1391
-
1392
- num_morph_normals = geometry_group[:num_morph_normals]
1393
-
1394
- if !num_morph_targets.zero?
1395
- geometry_group[:_morph_normals_arrays] = []
1396
-
1397
- num_morph_normals.times do |m|
1398
- geometry_group[:_morph_normals_arrays] << Array.new(nvertices * 3) # Float32Array ???
1399
- end
1400
- end
1401
-
1402
- geometry_group[:_opengl_face_count] = ntris * 3
1403
- geometry_group[:_opengl_line_count] = nlines * 2
1404
-
1405
- # custom attributes
1406
-
1407
- if material.attributes
1408
- if geometry_group[:_opengl_custom_attributes_list].nil?
1409
- geometry_group[:_opengl_custom_attributes_list] = []
1410
- end
1411
-
1412
- material.attributes.each do |(name, original_attribute)|
1413
- attribute = {}
1414
- original_attribute.each do |(key, value)|
1415
- attribute[key] = value
1416
- end
1417
-
1418
- if !attribute[:_opengl_initialized] || attribute[:create_unique_buffers]
1419
- attribute[:_opengl_initialized] = true
1420
-
1421
- size = case attribute[:type]
1422
- when :v2 then 2
1423
- when :v3, :c then 3
1424
- when :v4 then 4
1425
- else 1 # :f and :i
1426
- end
1427
-
1428
- attribute[:size] = size
1429
- attribute[:array] = Array.new(nvertices * size) # Float32Array
1430
-
1431
- attribute[:buffer] = glCreateBuffer
1432
- attribute[:buffer_belongs_to_attribute] = name
1433
-
1434
- original_attribute[:needs_update] = true
1435
- attribute[:_original] = original_attribute
1436
- end
1437
-
1438
- geometry_group[:_opengl_custom_attributes_list] << attribute
1439
- end
1440
- end
1441
-
1442
- geometry_group[:_initted_arrays] = true
1443
- end
1444
-
1445
- def update_object(object)
1446
- geometry = object.geometry
1447
-
1448
- if geometry.is_a? BufferGeometry
1449
- # TODO: geomertry vertex array ?????
1450
- # glBindVertexArray geometry.vertex_array
1451
-
1452
- geometry.attributes.each do |(key, attribute)|
1453
- buffer_type = (key == 'index') ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER
1454
-
1455
- if attribute.buffer.nil?
1456
- attribute.buffer = glCreateBuffer
1457
- glBindBuffer(buffer_type, attribute.buffer)
1458
- glBufferData_easy(buffer_type, attribute.array, (attribute.is_a? DynamicBufferAttribute) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW)
1459
-
1460
- attribute.needs_update = false
1461
- elsif attribute.needs_update
1462
- glBindBuffer(buffer_type, attribute.buffer)
1463
- if attribute.update_range.nil? || attribute.update_range.count == -1 # Not using update ranged
1464
- glBufferSubData(buffer_type, 0, attribute.array)
1465
- elsif attribute.udpate_range.count.zero?
1466
- puts 'ERROR: Mittsu::OpenGLRenderer#update_object: using update_range for Mittsu::DynamicBufferAttribute and marked as needs_update but count is 0, ensure you are using set methods or updating manually.'
1467
- else
1468
- # TODO: make a glBufferSubData_easy method
1469
- glBufferSubData(buffer_type, attribute.update_range.offset * attribute.array.BYTES_PER_ELEMENT, attribute.array.subarray(attribute.update_range.offset, attribute.update_range.offset + attribute.update_range.count))
1470
- attribute.update_range.count = 0 # reset range
1471
- end
1472
-
1473
- attribute.needs_update = false
1474
- end
1475
- end
1476
- elsif object.is_a? Mesh
1477
- # check all geometry groups
1478
- if geometry.groups_need_update
1479
- init_geometry_groups(object, geometry)
1480
- end
1481
-
1482
- geometry_groups_list = @geometry_groups[geometry.id]
1483
-
1484
- material = nil
1485
- geometry_groups_list.each do |geometry_group|
1486
- # TODO: place to put this???
1487
- # glBindVertexArray(geometry_group[:_opengl_vertex_array])
1488
- material = get_buffer_material(object, geometry_group)
1489
-
1490
- custom_attributes_dirty = material.attributes && are_custom_attributes_dirty(material)
1491
-
1492
- if geometry.vertices_need_update || geometry.morph_targets_need_update || geometry.elements_need_update || geometry.uvs_need_update || geometry.normals_need_update || geometry.colors_need_update || geometry.tangents_need_update || custom_attributes_dirty
1493
- set_mesh_buffers(geometry_group, object, GL_DYNAMIC_DRAW, !geometry.dynamic, material)
1494
- end
1495
- end
1496
-
1497
- geometry.vertices_need_update = false
1498
- geometry.morph_targets_need_update = false
1499
- geometry.elements_need_update = false
1500
- geometry.uvs_need_update = false
1501
- geometry.normals_need_update = false
1502
- geometry.colors_need_update = false
1503
- geometry.tangents_need_update = false
1504
-
1505
- material.attributes && clear_custom_attributes(material)
1506
- elsif (object.is_a? Line)
1507
- # TODO: glBindVertexArray ???
1508
- material = get_buffer_material(object, geometry)
1509
- custom_attributes_dirty = material.attributes && are_custom_attributes_dirty(material)
1510
-
1511
- if geometry.vertices_need_update || geometry.colors_need_update || geometry.line_distances_need_update || custom_attributes_dirty
1512
- set_line_buffers(geometry, GL_DYNAMIC_DRAW)
1513
- end
1514
-
1515
- geometry.vertices_need_update = false
1516
- geometry.colors_need_update = false
1517
- geometry.line_distances_need_update = false
1518
-
1519
- material.attributes && clear_custom_attributes(material)
1520
- elsif object.is_A? PointCloud
1521
- # TODO: glBindVertexArray ???
1522
- material = get_buffer_material(object, geometry)
1523
- custom_attributes_dirty = material.attributes && are_custom_attributes_dirty(material)
1524
-
1525
- if geometry.vertices_need_update || geometry.colors_need_update || custom_attributes_dirty
1526
- set_particle_buffers(geometry, GL_DYNAMIC_DRAW, object)
1527
- end
1528
-
1529
- geometry.vertices_need_update = false
1530
- geometry.colors_need_update = false
1531
-
1532
- material.attributes && clear_custom_attributes(material)
1533
- end
1534
- end
1535
-
1536
- def get_buffer_material(object, geometry_group)
1537
- # TODO: when MeshFaceMaterial exists
1538
- # object.material.is_a?(MeshFaceMaterial) ? object.material.materials[geometry_group[:material_index]] : object.material
1539
-
1540
- object.material # for now...
1541
- end
1542
-
1543
- def set_line_buffers(geometry, hint)
1544
- vertices = geometry.vertices
1545
- colors = geometry.colors
1546
- line_distances = geometry.line_distances_need_update
1547
-
1548
- vertex_array = geometry[:_vertex_array]
1549
- color_array = geometry[:_color_array]
1550
- line_distance_array = geometry[:_line_distance_array]
1551
-
1552
- custom_attributes = geometry[:_opengl_custom_attributes_list]
1553
-
1554
- if geometry.vertices_need_update
1555
- vertices.each_with_index do |vertex, v|
1556
- offset = v * 3
1557
-
1558
- vertex_array[offset] = vertex.x
1559
- vertex_array[offset + 1] = vertex.y
1560
- vertex_array[offset + 2] = vertex.z
1561
- end
1562
-
1563
- glBindBuffer(GL_ARRAY_BUFFER, geometry[:_opengl_vertex_buffer])
1564
- glBufferData_easy(GL_ARRAY_BUFFER, vertex_array, hint)
1565
- end
1566
-
1567
- if geometry.colors_need_update
1568
- colors.each_with_index do |color, c|
1569
- offset = c * 3
1570
-
1571
- color_array[offset] = color.r
1572
- color_array[offset + 1] = color.g
1573
- color_array[offset + 2] = color.b
1574
- end
1575
-
1576
- glBindBuffer(GL_ARRAY_BUFFER, geometry[:_opengl_color_buffer])
1577
- glBufferData_easy(GL_ARRAY_BUFFER, color_array, hint)
1578
- end
1579
-
1580
- if geometry.line_distances_need_update
1581
- line_distances.each_with_index do |l, d|
1582
- line_distance_array[d] = l
1583
- end
1584
-
1585
- glBindBuffer(GL_ARRAY_BUFFER, geometry[:_opengl_line_distance_buffer])
1586
- glBufferData_easy(GL_ARRAY_BUFFER, line_distance_array, hint)
1587
- end
1588
-
1589
- if custom_attributes
1590
- custom_attribute.each do |custom_attribute|
1591
- offset = 0
1592
-
1593
- values = custom_attribute.value
1594
-
1595
- case custom_attribute.size
1596
- when 1
1597
- value.each_with_index do |value, ca|
1598
- custom_attribute.array[ca] = value
1599
- end
1600
- when 2
1601
- values.each_with_index do |value, ca|
1602
- custom_attribute[offset ] = value.x
1603
- custom_attribute[offset + 1] = value.y
1604
-
1605
- offset += 2
1606
- end
1607
- when 3
1608
- if custom_attribute.type === :c
1609
- values.each_with_index do |value, ca|
1610
- custom_attribute[offset ] = value.r
1611
- custom_attribute[offset + 1] = value.g
1612
- custom_attribute[offset + 2] = value.b
1613
-
1614
- offset += 3
1615
- end
1616
- else
1617
- values.each_with_index do |value, ca|
1618
- custom_attribute[offset ] = value.x
1619
- custom_attribute[offset + 1] = value.y
1620
- custom_attribute[offset + 2] = value.z
1621
-
1622
- offset += 3
1623
- end
1624
- end
1625
- when 4
1626
- values.each_with_index do |value, ca|
1627
- custom_attribute[offset ] = value.x
1628
- custom_attribute[offset + 1] = value.y
1629
- custom_attribute[offset + 2] = value.z
1630
- custom_attribute[offset + 3] = value.w
1631
-
1632
- offset += 4
1633
- end
1634
- end
1635
-
1636
- glBindBuffer(GL_ARRAY_BUFFER, custom_attribute.buffer)
1637
- glBufferData_easy(GL_ARRAY_BUFFER, custom_attribute.array, hint)
1638
-
1639
- custom_attribute.needs_update = false
1640
- end
1641
- end
1642
- end
1643
-
1644
- def set_mesh_buffers(geometry_group, object, hint, dispose, material)
1645
- return unless geometry_group[:_initted_arrays]
1646
-
1647
- needs_face_normals = material_needs_face_normals(material)
1648
-
1649
- vertex_index = 0
1650
-
1651
- offset = 0
1652
- offset_uv = 0
1653
- offset_uv2 = 0
1654
- offset_face = 0
1655
- offset_normal = 0
1656
- offset_tangent = 0
1657
- offset_line = 0
1658
- offset_color = 0
1659
- offset_skin = 0
1660
- offset_morph_target = 0
1661
- offset_custom = 0
1662
-
1663
- vertex_array = geometry_group[:_vertex_array]
1664
- uv_array = geometry_group[:_uv_array]
1665
- uv2_array = geometry_group[:_uv2_array]
1666
- normal_array = geometry_group[:_normal_array]
1667
- tangent_array = geometry_group[:_tangent_array]
1668
- color_array = geometry_group[:_color_array]
1669
-
1670
- skin_index_array = geometry_group[:_skin_index_array]
1671
- skin_weight_array = geometry_group[:_skin_weight_array]
1672
-
1673
- morph_targets_arrays = geometry_group[:_morph_targets_arrays]
1674
- morph_normals_arrays = geometry_group[:_morph_normals_arrays]
1675
-
1676
- custom_attributes = geometry_group[:_opengl_custom_attributes_list]
1677
-
1678
- face_array = geometry_group[:_face_array]
1679
- line_array = geometry_group[:_line_array]
1680
-
1681
- geometry = object.geometry # this is shared for all chunks
1682
-
1683
- dirty_vertices = geometry.vertices_need_update
1684
- dirty_elements = geometry.elements_need_update
1685
- dirty_uvs = geometry.uvs_need_update
1686
- dirty_normals = geometry.normals_need_update
1687
- dirty_tangents = geometry.tangents_need_update
1688
- dirty_colors = geometry.colors_need_update
1689
- dirty_morph_targets = geometry.morph_targets_need_update
1690
-
1691
- vertices = geometry.vertices
1692
- chunk_faces3 = geometry_group[:faces3]
1693
- obj_faces = geometry.faces
1694
-
1695
- obj_uvs = geometry.face_vertex_uvs[0]
1696
- obj_uvs2 = geometry.face_vertex_uvs[1]
1697
-
1698
- obj_skin_indices = geometry.skin_indices
1699
- obj_skin_weights = geometry.skin_weights
1700
-
1701
- morph_targets = geometry.morph_targets
1702
- morph_normals = geometry.morph_normals
1703
-
1704
- if dirty_vertices
1705
- chunk_faces3.each do |chf|
1706
- face = obj_faces[chf]
1707
-
1708
- v1 = vertices[face.a]
1709
- v2 = vertices[face.b]
1710
- v3 = vertices[face.c]
1711
-
1712
- vertex_array[offset] = v1.x
1713
- vertex_array[offset + 1] = v1.y
1714
- vertex_array[offset + 2] = v1.z
1715
-
1716
- vertex_array[offset + 3] = v2.x
1717
- vertex_array[offset + 4] = v2.y
1718
- vertex_array[offset + 5] = v2.z
1719
-
1720
- vertex_array[offset + 6] = v3.x
1721
- vertex_array[offset + 7] = v3.y
1722
- vertex_array[offset + 8] = v3.z
1723
-
1724
- offset += 9
1725
- end
1726
-
1727
- glBindBuffer(GL_ARRAY_BUFFER, geometry_group[:_opengl_vertex_buffer])
1728
- glBufferData_easy(GL_ARRAY_BUFFER, vertex_array, hint)
1729
- end
1730
-
1731
- if dirty_morph_targets
1732
- morph_targets.each_index do |vk|
1733
- chunk_faces.each do |chf|
1734
- face = obj_faces[chf]
1735
-
1736
- # morph positions
1737
-
1738
- v1 = morph_targets[vk].vertices[face.a]
1739
- v2 = morph_targets[vk].vertices[face.b]
1740
- v3 = morph_targets[vk].vertices[face.c]
1741
-
1742
- vka = morph_targets_arrays[vk]
1743
-
1744
- vka[offset_morph_target] = v1.x
1745
- vka[offset_morph_target + 1] = v1.y
1746
- vka[offset_morph_target + 2] = v1.z
1747
-
1748
- vka[offset_morph_target + 3] = v2.x
1749
- vka[offset_morph_target + 4] = v2.y
1750
- vka[offset_morph_target + 5] = v2.z
1751
-
1752
- vka[offset_morph_target + 6] = v3.x
1753
- vka[offset_morph_target + 7] = v3.y
1754
- vka[offset_morph_target + 8] = v3.z
1755
-
1756
- # morph normals
1757
-
1758
- if material.morph_normals
1759
- if needs_face_normals
1760
- n1 = morph_normals[vk].face_normals[chf]
1761
- n2 = n1
1762
- n3 = n1
1763
- else
1764
- face_vertex_normals = morph_normals[vk].vertex_normals[chf]
1765
-
1766
- n1 = face_vertex_normals.a
1767
- n2 = face_vertex_normals.b
1768
- n3 = face_vertex_normals.c
1769
- end
1770
-
1771
- nka = morph_normals_arrays[vk]
1772
-
1773
- nka[offset_morph_target] = n1.x
1774
- nka[offset_morph_target + 1] = n1.y
1775
- nka[offset_morph_target + 2] = n1.z
1776
-
1777
- nka[offset_morph_target + 3] = n2.x
1778
- nka[offset_morph_target + 4] = n2.y
1779
- nka[offset_morph_target + 5] = n2.z
1780
-
1781
- nka[offset_morph_target + 6] = n3.x
1782
- nka[offset_morph_target + 7] = n3.y
1783
- nka[offset_morph_target + 8] = n3.z
1784
- end
1785
-
1786
- #
1787
-
1788
- offset_morph_target += 9
1789
- end
1790
-
1791
- glBindBuffer(GL_ARRAY_BUFFER, geometry_group[:_opengl_morph_targets_buffers][vk])
1792
- glBufferData_easy(GL_ARRAY_BUFFER, morph_targets_arrays[vk], hint)
1793
-
1794
- if material.morph_normals
1795
- glBindBuffer(GL_ARRAY_BUFFER, geometry_group[:_opengl_morph_normals_buffers][vk])
1796
- glBufferData_easy(GL_ARRAY_BUFFER, morph_normals_arrays[vk], hint)
1797
- end
1798
- end
1799
- end
1800
-
1801
- if !obj_skin_weights.empty?
1802
- chunk_faces3.each do |chf|
1803
- face = obj_faces[chf]
1804
-
1805
- # weights
1806
-
1807
- sw1 = obj_skin_weights[face.a]
1808
- sw2 = obj_skin_weights[face.b]
1809
- sw3 = obj_skin_weights[face.c]
1810
-
1811
- skin_weight_array[offset_skin] = sw1.x
1812
- skin_weight_array[offset_skin + 1] = sw1.y
1813
- skin_weight_array[offset_skin + 2] = sw1.z
1814
- skin_weight_array[offset_skin + 3] = sw1.w
1815
-
1816
- skin_weight_array[offset_skin + 4] = sw2.x
1817
- skin_weight_array[offset_skin + 5] = sw2.y
1818
- skin_weight_array[offset_skin + 6] = sw2.z
1819
- skin_weight_array[offset_skin + 7] = sw2.w
1820
-
1821
- skin_weight_array[offset_skin + 8] = sw3.x
1822
- skin_weight_array[offset_skin + 9] = sw3.y
1823
- skin_weight_array[offset_skin + 10] = sw3.z
1824
- skin_weight_array[offset_skin + 11] = sw3.w
1825
-
1826
- # indices
1827
-
1828
- si1 = obj_skin_indices[face.a]
1829
- si2 = obj_skin_indices[face.b]
1830
- si3 = obj_skin_indices[face.c]
1831
-
1832
- skin_indices_array[offset_skin] = si1.x
1833
- skin_indices_array[offset_skin + 1] = si1.y
1834
- skin_indices_array[offset_skin + 2] = si1.z
1835
- skin_indices_array[offset_skin + 3] = si1.w
1836
-
1837
- skin_indices_array[offset_skin + 4] = si2.x
1838
- skin_indices_array[offset_skin + 5] = si2.y
1839
- skin_indices_array[offset_skin + 6] = si2.z
1840
- skin_indices_array[offset_skin + 7] = si2.w
1841
-
1842
- skin_indices_array[offset_skin + 8] = si3.x
1843
- skin_indices_array[offset_skin + 9] = si3.y
1844
- skin_indices_array[offset_skin + 10] = si3.z
1845
- skin_indices_array[offset_skin + 11] = si3.w
1846
-
1847
- offset_skin += 12
1848
- end
1849
-
1850
- if offset_skin > 0
1851
- glBindBuffer(GL_ARRAY_BUFFER, geometry_group[:_opengl_skin_indices_buffer])
1852
- glBufferData_easy(GL_ARRAY_BUFFER, skin_index_array, hint)
1853
-
1854
- glBindBuffer(GL_ARRAY_BUFFER, geometry_group[:_opengl_skin_weights_buffer])
1855
- glBufferData_easy(GL_ARRAY_BUFFER, skin_weight_array, hint)
1856
- end
1857
- end
1858
-
1859
- if dirty_colors
1860
- chunk_faces3.each do |chf|
1861
- face = obj_faces[chf]
1862
-
1863
- vertex_colors = face.vertex_colors
1864
- face_color = face.color
1865
-
1866
- if vertex_colors.length == 3 && material.vertex_colors == VertexColors
1867
- c1 = vertex_colors[0]
1868
- c2 = vertex_colors[1]
1869
- c3 = vertex_colors[2]
1870
- else
1871
- c1 = face_color
1872
- c2 = face_color
1873
- c3 = face_color
1874
- end
1875
-
1876
- color_array[offset_color] = c1.r
1877
- color_array[offset_color + 1] = c1.g
1878
- color_array[offset_color + 2] = c1.b
1879
-
1880
- color_array[offset_color + 3] = c2.r
1881
- color_array[offset_color + 4] = c2.g
1882
- color_array[offset_color + 5] = c2.b
1883
-
1884
- color_array[offset_color + 6] = c3.r
1885
- color_array[offset_color + 7] = c3.g
1886
- color_array[offset_color + 8] = c3.b
1887
-
1888
- offset_color += 9
1889
- end
1890
-
1891
- if offset_color > 0
1892
- glBindBuffer(GL_ARRAY_BUFFER, geometry_group[:_opengl_color_buffer])
1893
- glBufferData_easy(GL_ARRAY_BUFFER, color_array, hint)
1894
- end
1895
- end
1896
-
1897
- if dirty_tangents && geometry.has_tangents
1898
- chunk_faces3.each do |chf|
1899
- face = obj_faces[chf]
1900
-
1901
- vertex_tangents = face.vertex_tangents
1902
-
1903
- t1 = vertex_tangents[0]
1904
- t2 = vertex_tangents[1]
1905
- t3 = vertex_tangents[2]
1906
-
1907
- tangent_array[offset_tangent] = t1.x
1908
- tangent_array[offset_tangent + 1] = t1.y
1909
- tangent_array[offset_tangent + 2] = t1.z
1910
- tangent_array[offset_tangent + 3] = t1.w
1911
-
1912
- tangent_array[offset_tangent + 4] = t2.x
1913
- tangent_array[offset_tangent + 5] = t2.y
1914
- tangent_array[offset_tangent + 6] = t2.z
1915
- tangent_array[offset_tangent + 7] = t2.w
1916
-
1917
- tangent_array[offset_tangent + 8] = t3.x
1918
- tangent_array[offset_tangent + 9] = t3.y
1919
- tangent_array[offset_tangent + 10] = t3.z
1920
- tangent_array[offset_tangent + 11] = t3.w
1921
-
1922
- offset_tangent += 12
1923
- end
1924
-
1925
- glBindBuffer(GL_ARRAY_BUFFER, geometry_group[:_opengl_tangent_buffer])
1926
- glBufferData_easy(GL_ARRAY_BUFFER, tangent_array, hint)
1927
- end
1928
-
1929
- if dirty_normals
1930
- chunk_faces3.each do |chf|
1931
- face = obj_faces[chf]
1932
-
1933
- vertex_normals = face.vertex_normals
1934
- face_normal = face.normal
1935
-
1936
- if vertex_normals.length == 3 && !needs_face_normals
1937
- 3.times do |i|
1938
- vn = vertex_normals[i]
1939
-
1940
- normal_array[offset_normal] = vn.x
1941
- normal_array[offset_normal + 1] = vn.y
1942
- normal_array[offset_normal + 2] = vn.z
1943
-
1944
- offset_normal += 3
1945
- end
392
+ def render_objects_immediate(render_list, material_type, camera, lights, fog, override_material)
393
+ material = nil
394
+ render_list.each do |opengl_object|
395
+ object = opengl_object.object
396
+ if object.visible
397
+ if override_material
398
+ material = override_material
1946
399
  else
1947
- 3.times do |i|
1948
- normal_array[offset_normal] = face_normal.x
1949
- normal_array[offset_normal + 1] = face_normal.y
1950
- normal_array[offset_normal + 2] = face_normal.z
1951
-
1952
- offset_normal += 3
400
+ material = case material_type
401
+ when :transparent then opengl_object.transparent
402
+ when :opaque then opengl_object.opaque
403
+ else nil
1953
404
  end
405
+ next unless material
406
+ material_impl = material.implementation(self)
407
+ material_impl.set
1954
408
  end
1955
- end
1956
-
1957
- glBindBuffer(GL_ARRAY_BUFFER, geometry_group[:_opengl_normal_buffer])
1958
- glBufferData_easy(GL_ARRAY_BUFFER, normal_array, hint)
1959
- end
1960
-
1961
- if dirty_uvs && obj_uvs
1962
- chunk_faces3.each do |fi|
1963
- uv = obj_uvs[fi]
1964
-
1965
- next if uv.nil?
1966
-
1967
- 3.times do |i|
1968
- uvi = uv[i]
1969
-
1970
- uv_array[offset_uv] = uvi.x
1971
- uv_array[offset_uv + 1] = uvi.y
1972
-
1973
- offset_uv += 2
1974
- end
1975
- end
1976
-
1977
- if offset_uv > 0
1978
- glBindBuffer(GL_ARRAY_BUFFER, geometry_group[:_opengl_uv_buffer])
1979
- glBufferData_easy(GL_ARRAY_BUFFER, uv_array, hint)
409
+ render_immediate_object(camera, lights, fog, material, object)
1980
410
  end
1981
411
  end
412
+ end
1982
413
 
1983
- if dirty_uvs && obj_uvs2
1984
- chunk_faces3.each do |fi|
1985
- uv2 = obj_uvs2[fi]
414
+ def add_buffer(objlist, buffer, object)
415
+ id = object.id
416
+ (objlist[id] ||= []) << OpenGLBuffer.new(
417
+ buffer, object, nil, 0
418
+ )
419
+ end
1986
420
 
1987
- next if uv2.nil?
421
+ def unroll_immediate_buffer_material(opengl_object)
422
+ object = opengl_object.object
423
+ material = object.material
1988
424
 
1989
- 3.times do |i|
1990
- uv2i = uv2[i]
425
+ if material.transparent
426
+ opengl_object.transparent
427
+ opengl_object.opaque = nil
428
+ else
429
+ opengl_object.opaque = material
430
+ opengl_object.transparent = nil
431
+ end
432
+ end
1991
433
 
1992
- uv2_array[offset_uv2] = uv2i.x
1993
- uv2_array[offset_uv2 + 1] = uv2i.y
434
+ def unroll_buffer_material(opengl_object)
435
+ object = opengl_object.object
436
+ buffer = opengl_object.buffer
1994
437
 
1995
- offset_uv2 += 2
1996
- end
1997
- end
438
+ geometry = object.geometry
439
+ material = object.material
1998
440
 
1999
- if offset_uv2 > 0
2000
- glBindBuffer(GL_ARRAY_BUFFER, geometry_group[:_opengl_uv2_buffer])
2001
- glBufferData_easy(GL_ARRAY_BUFFER, uv2_array, hint)
441
+ if material
442
+ if material.is_a? MeshFaceMaterial
443
+ material_index = geometry.is_a?(BufferGeometry) ? 0 : buffer.material_index
444
+ material = material.materials[material_index]
2002
445
  end
2003
- end
2004
-
2005
- if dirty_elements
2006
- chunk_faces3.each do |chf|
2007
- face_array[offset_face] = vertex_index
2008
- face_array[offset_face + 1] = vertex_index + 1
2009
- face_array[offset_face + 2] = vertex_index + 2
2010
-
2011
- offset_face += 3
2012
-
2013
- line_array[offset_line] = vertex_index
2014
- line_array[offset_line + 1] = vertex_index + 1
2015
446
 
2016
- line_array[offset_line + 2] = vertex_index
2017
- line_array[offset_line + 3] = vertex_index + 2
447
+ opengl_object.material = material
2018
448
 
2019
- line_array[offset_line + 4] = vertex_index + 1
2020
- line_array[offset_line + 5] = vertex_index + 2
2021
-
2022
- offset_line += 6
2023
-
2024
- vertex_index += 3
449
+ if material.transparent
450
+ @transparent_objects << opengl_object
451
+ else
452
+ @opaque_objects << opengl_object
2025
453
  end
2026
-
2027
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometry_group[:_opengl_face_buffer])
2028
- glBufferData_easy(GL_ELEMENT_ARRAY_BUFFER, face_array, hint)
2029
-
2030
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometry_group[:_opengl_line_buffer])
2031
- glBufferData_easy(GL_ELEMENT_ARRAY_BUFFER, line_array, hint)
2032
454
  end
455
+ end
2033
456
 
2034
- if custom_attributes
2035
- custom_attributes.each do |custom_attribute|
2036
- next if !custom_attribute[:_original][:needs_update]
2037
-
2038
- offset_custom = 0
2039
-
2040
- if custom_attribute[:size] == 1
2041
- if custom_attribute[:bound_to].nil? || custom_attribute[:bound_to] == :vertices
2042
- chunk_faces3.each do |chf|
2043
- face = obj_faces[chf]
457
+ # FIXME: refactor
458
+ def update_object(object)
459
+ geometry = object.geometry
460
+ object_impl = object.implementation(self)
2044
461
 
2045
- custom_attribute[:array][offset_custom] = custom_attribute[:value][face.a]
2046
- custom_attribute[:array][offset_custom + 1] = custom_attribute[:value][face.b]
2047
- custom_attribute[:array][offset_custom + 2] = custom_attribute[:value][face.c]
462
+ if geometry.is_a? BufferGeometry
463
+ # TODO: geometry vertex array ?????
464
+ # glBindVertexArray geometry.vertex_array
2048
465
 
2049
- offset_custom += 3
2050
- end
2051
- elsif custom_attribute[:bound_to] == :faces
2052
- value = custom_attribute[:value][chf]
466
+ geometry.attributes.each do |(key, attribute)|
467
+ buffer_type = (key == 'index') ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER
2053
468
 
2054
- custom_attribute[:array][offset_custom] = value
2055
- custom_attribute[:array][offset_custom + 1] = value
2056
- custom_attribute[:array][offset_custom + 2] = value
469
+ if attribute.buffer.nil?
470
+ attribute.buffer = glCreateBuffer
471
+ glBindBuffer(buffer_type, attribute.buffer)
472
+ glBufferData_easy(buffer_type, attribute.array, (attribute.is_a? DynamicBufferAttribute) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW)
2057
473
 
2058
- offset_custom += 3
474
+ attribute.needs_update = false
475
+ elsif attribute.needs_update
476
+ glBindBuffer(buffer_type, attribute.buffer)
477
+ if attribute.update_range.nil? || attribute.update_range.count == -1 # Not using update ranged
478
+ glBufferSubData(buffer_type, 0, attribute.array)
479
+ elsif attribute.udpate_range.count.zero?
480
+ puts 'ERROR: Mittsu::OpenGLRenderer#update_object: using update_range for Mittsu::DynamicBufferAttribute and marked as needs_update but count is 0, ensure you are using set methods or updating manually.'
481
+ else
482
+ # TODO: make a glBufferSubData_easy method
483
+ glBufferSubData(buffer_type, attribute.update_range.offset * attribute.array.BYTES_PER_ELEMENT, attribute.array.subarray(attribute.update_range.offset, attribute.update_range.offset + attribute.update_range.count))
484
+ attribute.update_range.count = 0 # reset range
2059
485
  end
2060
- elsif custom_attribute[:size] == 2
2061
- if custom_attribute[:bound_to].nil? || custom_attribute[:bound_to] == :vertices
2062
- chunk_faces3.each do |chf|
2063
- face = obj_faces[chf]
2064
-
2065
- v1 = custom_attribute[:value][face.a]
2066
- v2 = custom_attribute[:value][face.b]
2067
- v3 = custom_attribute[:value][face.c]
2068
-
2069
- custom_attribute[:array][offset_custom] = v1.x
2070
- custom_attribute[:array][offset_custom + 1] = v1.y
2071
-
2072
- custom_attribute[:array][offset_custom + 2] = v2.x
2073
- custom_attribute[:array][offset_custom + 3] = v2.y
2074
-
2075
- custom_attribute[:array][offset_custom + 4] = v3.x
2076
- custom_attribute[:array][offset_custom + 5] = v3.y
2077
-
2078
- offset_custom += 6
2079
- end
2080
- elsif custom_attribute[:bound_to] == :faces
2081
- chunk_faces3.each do |chf|
2082
- value = custom_attribute[:value][chf]
2083
-
2084
- v1 = value
2085
- v2 = value
2086
- v3 = value
2087
486
 
2088
- custom_attribute[:array][offset_custom] = v1.x
2089
- custom_attribute[:array][offset_custom + 1] = v1.y
2090
-
2091
- custom_attribute[:array][offset_custom + 2] = v2.x
2092
- custom_attribute[:array][offset_custom + 3] = v2.y
2093
-
2094
- custom_attribute[:array][offset_custom + 4] = v3.x
2095
- custom_attribute[:array][offset_custom + 5] = v3.y
2096
-
2097
- offset_custom += 6
2098
- end
2099
- end
2100
- elsif custom_attribute[:size] == 3
2101
- if custom_attribute[:bound_to].nil? || custom_attribute[:bound_to] == :vertices
2102
- chunk_faces3.each do |chf|
2103
- face = obj_faces[chf];
2104
-
2105
- v1 = custom_attribute[:value][face.a]
2106
- v2 = custom_attribute[:value][face.b]
2107
- v3 = custom_attribute[:value][face.c]
2108
-
2109
- custom_attribute[:array][offset_custom] = v1[0]
2110
- custom_attribute[:array][offset_custom + 1] = v1[1]
2111
- custom_attribute[:array][offset_custom + 2] = v1[2]
2112
-
2113
- custom_attribute[:array][offset_custom + 3] = v2[0]
2114
- custom_attribute[:array][offset_custom + 4] = v2[1]
2115
- custom_attribute[:array][offset_custom + 5] = v2[2]
2116
-
2117
- custom_attribute[:array][offset_custom + 6] = v3[0]
2118
- custom_attribute[:array][offset_custom + 7] = v3[1]
2119
- custom_attribute[:array][offset_custom + 8] = v3[2]
2120
-
2121
- offset_custom += 9
2122
- end
2123
- elsif custom_attribute[:bound_to] == :faces
2124
- chunk_faces3.each do |chf|
2125
- value = custom_attribute[:value][chf]
2126
-
2127
- v1 = value
2128
- v2 = value
2129
- v3 = value
2130
-
2131
- custom_attribute[:array][offset_custom] = v1[0]
2132
- custom_attribute[:array][offset_custom + 1] = v1[1]
2133
- custom_attribute[:array][offset_custom + 2] = v1[2]
2134
-
2135
- custom_attribute[:array][offset_custom + 3] = v2[0]
2136
- custom_attribute[:array][offset_custom + 4] = v2[1]
2137
- custom_attribute[:array][offset_custom + 5] = v2[2]
2138
-
2139
- custom_attribute[:array][offset_custom + 6] = v3[0]
2140
- custom_attribute[:array][offset_custom + 7] = v3[1]
2141
- custom_attribute[:array][offset_custom + 8] = v3[2]
2142
-
2143
- offset_custom += 9
2144
- end
2145
- elsif custom_attribute[:bound_to] == :face_vertices
2146
- chunk_faces3.each do |chf|
2147
- value = custom_attribute[:value][chf]
2148
-
2149
- v1 = value[0]
2150
- v2 = value[1]
2151
- v3 = value[2]
2152
-
2153
- custom_attribute[:array][offset_custom] = v1[0]
2154
- custom_attribute[:array][offset_custom + 1] = v1[1]
2155
- custom_attribute[:array][offset_custom + 2] = v1[2]
2156
-
2157
- custom_attribute[:array][offset_custom + 3] = v2[0]
2158
- custom_attribute[:array][offset_custom + 4] = v2[1]
2159
- custom_attribute[:array][offset_custom + 5] = v2[2]
2160
-
2161
- custom_attribute[:array][offset_custom + 6] = v3[0]
2162
- custom_attribute[:array][offset_custom + 7] = v3[1]
2163
- custom_attribute[:array][offset_custom + 8] = v3[2]
2164
-
2165
- offset_custom += 9
2166
- end
2167
- end
2168
- elsif custom_attribute[:size] == 4
2169
- if custom_attribute[:bound_to].nil? || custom_attribute[:bound_to] == :vertices
2170
- chunk_faces3.each do |chf|
2171
- face = obj_faces[chf]
2172
-
2173
- v1 = custom_attribute[:value][face.a]
2174
- v2 = custom_attribute[:value][face.b]
2175
- v3 = custom_attribute[:value][face.c]
2176
-
2177
- customAttribute.array[offset_custom] = v1.x
2178
- customAttribute.array[offset_custom + 1 ] = v1.y
2179
- customAttribute.array[offset_custom + 2 ] = v1.z
2180
- customAttribute.array[offset_custom + 3 ] = v1.w
2181
-
2182
- customAttribute.array[offset_custom + 4 ] = v2.x
2183
- customAttribute.array[offset_custom + 5 ] = v2.y
2184
- customAttribute.array[offset_custom + 6 ] = v2.z
2185
- customAttribute.array[offset_custom + 7 ] = v2.w
2186
-
2187
- customAttribute.array[offset_custom + 8 ] = v3.x
2188
- customAttribute.array[offset_custom + 9 ] = v3.y
2189
- customAttribute.array[offset_custom + 10] = v3.z
2190
- customAttribute.array[offset_custom + 11] = v3.w
2191
-
2192
- offset_custom += 12
2193
- end
2194
- elsif custom_attribute[:bound_to] == :faces
2195
- chunk_faces3.each do |chf|
2196
- value = custom_attribute[:value][chf]
2197
-
2198
- v1 = value
2199
- v2 = value
2200
- v3 = value
2201
-
2202
- customAttribute.array[offset_custom] = v1.x
2203
- customAttribute.array[offset_custom + 1 ] = v1.y
2204
- customAttribute.array[offset_custom + 2 ] = v1.z
2205
- customAttribute.array[offset_custom + 3 ] = v1.w
2206
-
2207
- customAttribute.array[offset_custom + 4 ] = v2.x
2208
- customAttribute.array[offset_custom + 5 ] = v2.y
2209
- customAttribute.array[offset_custom + 6 ] = v2.z
2210
- customAttribute.array[offset_custom + 7 ] = v2.w
2211
-
2212
- customAttribute.array[offset_custom + 8 ] = v3.x
2213
- customAttribute.array[offset_custom + 9 ] = v3.y
2214
- customAttribute.array[offset_custom + 10] = v3.z
2215
- customAttribute.array[offset_custom + 11] = v3.w
2216
-
2217
- offset_custom += 12
2218
- end
2219
- elsif custom_attribute[:bound_to] == :face_vertices
2220
- chunk_faces3.each do |chf|
2221
- value = custom_attribute[:value][chf]
2222
-
2223
- v1 = value[0]
2224
- v2 = value[1]
2225
- v3 = value[2]
2226
-
2227
- customAttribute.array[offset_custom] = v1.x
2228
- customAttribute.array[offset_custom + 1 ] = v1.y
2229
- customAttribute.array[offset_custom + 2 ] = v1.z
2230
- customAttribute.array[offset_custom + 3 ] = v1.w
2231
-
2232
- customAttribute.array[offset_custom + 4 ] = v2.x
2233
- customAttribute.array[offset_custom + 5 ] = v2.y
2234
- customAttribute.array[offset_custom + 6 ] = v2.z
2235
- customAttribute.array[offset_custom + 7 ] = v2.w
2236
-
2237
- customAttribute.array[offset_custom + 8 ] = v3.x
2238
- customAttribute.array[offset_custom + 9 ] = v3.y
2239
- customAttribute.array[offset_custom + 10] = v3.z
2240
- customAttribute.array[offset_custom + 11] = v3.w
2241
-
2242
- offset_custom += 12
2243
- end
2244
- end
487
+ attribute.needs_update = false
2245
488
  end
2246
-
2247
- glBindBuffer(GL_ARRAY_BUFFER, custom_attribute[:buffer])
2248
- glBufferData_easy(GL_ARRAY_BUFFER, custom_attribute[:array], hint)
2249
489
  end
490
+ else
491
+ object_impl.update
2250
492
  end
2251
-
2252
- if dispose
2253
- geometry_group.delete(:_initted_arrays)
2254
- geometry_group.delete(:_color_array)
2255
- geometry_group.delete(:_normal_array)
2256
- geometry_group.delete(:_tangent_array)
2257
- geometry_group.delete(:_uv_array)
2258
- geometry_group.delete(:_uv2_array)
2259
- geometry_group.delete(:_face_array)
2260
- geometry_group.delete(:_vertex_array)
2261
- geometry_group.delete(:_line_array)
2262
- geometry_group.delete(:_skin_index_array)
2263
- geometry_group.delete(:_skin_weight_array)
2264
- end
2265
- end
2266
-
2267
- def material_needs_face_normals(material)
2268
- !material.is_a?(MeshPhongMaterial) && material.shading == FlatShading
493
+ # TODO: when PointCloud exists
494
+ # elsif object.is_A? PointCloud
495
+ # # TODO: glBindVertexArray ???
496
+ # material = object_impl.buffer_material(geometry)
497
+ # custom_attributes_dirty = material.attributes && are_custom_attributes_dirty(material)
498
+ #
499
+ # if geometry.vertices_need_update || geometry.colors_need_update || custom_attributes_dirty
500
+ # set_particle_buffers(geometry, GL_DYNAMIC_DRAW, object)
501
+ # end
502
+ #
503
+ # geometry.vertices_need_update = false
504
+ # geometry.colors_need_update = false
505
+ #
506
+ # material.attributes && clear_custom_attributes(material)
507
+ # end
2269
508
  end
2270
509
 
510
+ # FIXME: refactor
2271
511
  def set_program(camera, lights, fog, material, object)
2272
512
  @_used_texture_units = 0
513
+ material_impl = material.implementation(self)
514
+ object_impl = object.implementation(self)
2273
515
 
2274
516
  if material.needs_update?
2275
517
  deallocate_material(material) if material.program
2276
518
 
2277
- init_material(material, lights, fog, object)
519
+ material_impl.init(lights, fog, object)
2278
520
  material.needs_update = false
2279
521
  end
2280
522
 
2281
523
  if material.morph_targets
2282
- if !object[:_opengl_morph_target_influences]
2283
- object[:_opengl_morph_target_influences] = Array.new(@max_morph_targets) # Float32Array
524
+ if !object_impl.morph_target_influences
525
+ object_impl.morph_target_influences = Array.new(@max_morph_targets) # Float32Array
2284
526
  end
2285
527
  end
2286
528
 
@@ -2289,8 +531,8 @@ module Mittsu
2289
531
  refresh_lights = false
2290
532
 
2291
533
  program = material.program
2292
- p_uniforms = program.uniforms
2293
- m_uniforms = material[:_opengl_shader][:uniforms]
534
+ program_uniforms = program.uniforms
535
+ material_uniforms = material_impl.shader[:uniforms]
2294
536
 
2295
537
  if program.id != @_current_program
2296
538
  glUseProgram(program.program)
@@ -2309,444 +551,92 @@ module Mittsu
2309
551
  end
2310
552
 
2311
553
  if refresh_program || camera != @_current_camera
2312
- glUniformMatrix4fv(p_uniforms['projectionMatrix'], 1, GL_FALSE, array_to_ptr_easy(camera.projection_matrix.elements))
2313
-
2314
- if @_logarithmic_depth_buffer
2315
- glUniform1f(p_uniforms['logDepthBuffFC'], 2.0 / Math.log(camera.far + 1.0) / Math::LN2)
2316
- end
2317
-
2318
- @_current_camera = camera if camera != @_current_camera
2319
-
2320
- # load material specific uniforms
2321
- # (shader material also gets them for the sake of genericity)
2322
-
2323
- if material.is_a?(ShaderMaterial) || material.is_a?(MeshPhongMaterial) || material.env_map
2324
- if !p_uniforms['cameraPosition'].nil?
2325
- @_vector3.set_from_matrix_position(camera.matrix_world)
2326
- glUniform3f(p_uniforms['cameraPosition'], @_vector3.x, @_vector3.y, @_vector3.z)
2327
- end
2328
- end
2329
-
2330
- if material.is_a?(MeshPhongMaterial) || material.is_a?(MeshLambertMaterial) || material.is_a?(MeshBasicMaterial) || material.is_a?(ShaderMaterial) || material.skinning
2331
- if !p_uniforms['viewMatrix'].nil?
2332
- glUniformMatrix4fv(p_uniforms['viewMatrix'], 1, GL_FALSE, array_to_ptr_easy(camera.matrix_world_inverse.elements))
2333
- end
2334
- end
554
+ @_current_camera = camera
555
+ update_camera_uniforms(program_uniforms, camera, material)
2335
556
  end
2336
557
 
2337
558
  if material.skinning
2338
- if object.bind_matrix && !p_uniforms.bind_matrix.nil?
2339
- glUniformMatrix4fv(p_uniforms.bind_matrix, GL_FALSE, object.bind_matrix.elements)
2340
- end
2341
-
2342
- if object.bind_matrix_inverse && !p_uniforms.bind_matrix_inverse.nil?
2343
- glUniformMatrix4fv(p_uniforms.bind_matrix_inverse, GL_FALSE, object.bind_matrix_inverse.elements)
2344
- end
2345
-
2346
- if _supports_bone_textures && object.skeleton && object.skeleton.use_vertex_texture
2347
- if !p_uniforms.bone_texture.nil?
2348
- texture_unit = get_texture_unit
2349
-
2350
- glUniform1i(p_uniforms.bone_texture, texture_unit)
2351
- self.set_texture(object.skeleton.bone_texture, texture_unit)
2352
- end
2353
-
2354
- if !p_uniforms.bone_texture_width.nil?
2355
- glUniform1i(p_uniforms.bone_texture_width, object.skeleton.bone_texture_width)
2356
- end
2357
-
2358
- if !p_uniforms.bone_texture_height.nil?
2359
- glUniform1i(p_uniforms.bone_texture_height, object.skeleton.bone_texture_height)
2360
- end
2361
- elsif object.skeleton && object.skeleton.bone_matrices
2362
- if !p_uniforms.bone_global_matrices.nil?
2363
- glUniformMatrix4fv(p_uniforms.bone_global_matrices, GL_FALSE, object.skeleton.bone_matrices)
2364
- end
2365
- end
2366
- end
2367
-
2368
- if refresh_material
2369
- if fog && material.fog
2370
- end
2371
-
2372
- if material.is_a?(MeshPhongMaterial) || material.is_a?(MeshLambertMaterial) || material.lights
2373
- if @_lights_need_update
2374
- refresh_lights = true
2375
- setup_lights(lights)
2376
- @_lights_need_update = false
2377
- end
2378
-
2379
- if refresh_lights
2380
- refresh_uniforms_lights(m_uniforms, @_lights)
2381
- mark_uniforms_lights_needs_update(m_uniforms, true)
2382
- else
2383
- mark_uniforms_lights_needs_update(m_uniforms, false)
2384
- end
2385
- end
2386
-
2387
- if material.is_a?(MeshBasicMaterial) || material.is_a?(MeshLambertMaterial) || material.is_a?(MeshPhongMaterial)
2388
- refresh_uniforms_common(m_uniforms, material)
2389
- end
2390
-
2391
- # refresh single material specific uniforms
2392
-
2393
- # TODO: when all of these things exist
2394
- case material
2395
- when LineBasicMaterial
2396
- refresh_uniforms_line(m_uniforms, material)
2397
- # when LineDashedMaterial
2398
- # refresh_uniforms_line(m_uniforms, material)
2399
- # refresh_uniforms_dash(m_uniforms, material)
2400
- # when PointCloudMaterial
2401
- # refresh_uniforms_particle(m_uniforms, material)
2402
- when MeshPhongMaterial
2403
- refresh_uniforms_phong(m_uniforms, material)
2404
- when MeshLambertMaterial
2405
- refresh_uniforms_lambert(m_uniforms, material)
2406
- # when MeshDepthMaterial
2407
- # m_uniforms.m_near.value = camera.near
2408
- # m_uniforms.m_far.value = camera.far
2409
- # m_uniforms.opacity.value = material.opacity
2410
- # when MeshNormalMaterial
2411
- # m_uniforms.opactity.value = material.opacity
2412
- end
2413
-
2414
- if object.receive_shadow && !material[:_shadow_pass]
2415
- refresh_uniforms_shadow(m_uniforms, lights)
2416
- end
2417
-
2418
- # load common uniforms
2419
-
2420
- load_uniforms_generic(material[:uniforms_list])
2421
- end
2422
-
2423
- load_uniforms_matrices(p_uniforms, object)
2424
-
2425
- if !p_uniforms['modelMatrix'].nil?
2426
- glUniformMatrix4fv(p_uniforms['modelMatrix'], 1, GL_FALSE, array_to_ptr_easy(object.matrix_world.elements))
2427
- end
2428
-
2429
- program
2430
- end
2431
-
2432
- def init_material(material, lights, fog, object)
2433
- material.add_event_listener(:dispose, @on_material_dispose)
2434
-
2435
- shader_id = @shader_ids[material.class]
2436
-
2437
- if shader_id
2438
- shader = ShaderLib[shader_id]
2439
- material[:_opengl_shader] = {
2440
- uniforms: UniformsUtils.clone(shader.uniforms),
2441
- vertex_shader: shader.vertex_shader,
2442
- fragment_shader: shader.fragment_shader
2443
- }
2444
- else
2445
- material[:_opengl_shader] = {
2446
- uniforms: material.uniforms,
2447
- vertex_shader: material.vertex_shader,
2448
- fragment_shader: material.fragment_shader
2449
- }
2450
- end
2451
-
2452
- # heuristics to create shader paramaters ccording to lights in the scene
2453
- # (not to blow over max_lights budget)
2454
-
2455
- max_light_count = allocate_lights(lights)
2456
- max_shadows = allocate_shadows(lights)
2457
- max_bones = allocate_bones(object)
2458
-
2459
- parameters = {
2460
- precision: @_precision,
2461
- supports_vertex_textures: @_supports_vertex_textures,
2462
-
2463
- map: !!material.map,
2464
- env_map: !!material.env_map,
2465
- env_map_mode: material.env_map && material.env_map.mapping,
2466
- light_map: !!material.light_map,
2467
- bump_map: !!material.light_map,
2468
- normal_map: !!material.normal_map,
2469
- specular_map: !!material.specular_map,
2470
- alpha_map: !!material.alpha_map,
2471
-
2472
- combine: material.combine,
2473
-
2474
- vertex_colors: material.vertex_colors,
2475
-
2476
- fog: fog,
2477
- use_fog: material.fog,
2478
- # fog_exp: fog.is_a?(FogExp2), # TODO: when FogExp2 exists
2479
-
2480
- flat_shading: material.shading == FlatShading,
2481
-
2482
- size_attenuation: material.size_attenuation,
2483
- logarithmic_depth_buffer: @_logarithmic_depth_buffer,
2484
-
2485
- skinning: material.skinning,
2486
- max_bones: max_bones,
2487
- use_vertex_texture: @_supports_bone_textures,
2488
-
2489
- morph_targets: material.morph_targets,
2490
- morph_normals: material.morph_normals,
2491
- max_morph_targets: @max_morph_targets,
2492
- max_morph_normals: @max_morph_normals,
2493
-
2494
- max_dir_lights: max_light_count[:directional],
2495
- max_point_lights: max_light_count[:point],
2496
- max_spot_lights: max_light_count[:spot],
2497
- max_hemi_lights: max_light_count[:hemi],
2498
-
2499
- max_shadows: max_shadows,
2500
- shadow_map_enabled: @shadow_map_enabled && object.receive_shadow && max_shadows > 0,
2501
- shadow_map_type: @shadow_map_type,
2502
- shadow_map_debug: @shadow_map_debug,
2503
- shadow_map_cascade: @shadow_map_cascade,
2504
-
2505
- alpha_test: material.alpha_test,
2506
- metal: material.metal,
2507
- wrap_around: material.wrap_around,
2508
- double_sided: material.side == DoubleSide,
2509
- flip_sided: material.side == BackSide
2510
- }
2511
-
2512
- # generate code
2513
-
2514
- chunks = []
2515
-
2516
- if shader_id
2517
- chunks << shader_id
2518
- else
2519
- chunks << material.fragment_shader
2520
- chunks << material.vertex_shader
2521
- end
2522
-
2523
- if !material.defines.nil?
2524
- material.defines.each do |(name, define)|
2525
- chunks << name
2526
- chunks << define
2527
- end
2528
- end
2529
-
2530
- parameters.each do |(name, parameter)|
2531
- chunks << name
2532
- chunks << parameter
2533
- end
2534
-
2535
- code = chunks.join
2536
-
2537
- program = nil
2538
-
2539
- # check if code has been already compiled
2540
-
2541
- @_programs.each do |program_info|
2542
- if program_info.code == code
2543
- program = program_info
2544
- program.used_times += 1
2545
- break
2546
- end
2547
- end
2548
-
2549
- if program.nil?
2550
- program = OpenGLProgram.new(self, code, material, parameters)
2551
- @_programs.push(program)
2552
-
2553
- @info[:memory][:programs] = @_programs.length
2554
- end
2555
-
2556
- material.program = program
2557
-
2558
- attributes = program.attributes
2559
-
2560
- if material.morph_targets
2561
- material.num_supported_morph_targets = 0
2562
- base = 'morphTarget'
2563
-
2564
- @max_morph_targets.times do |i|
2565
- id = base + i
2566
- if attributes[id] >= 0
2567
- material.num_supported_morph_targets += 1
2568
- end
2569
- end
2570
- end
2571
-
2572
- if material.morph_normals
2573
- material.num_supported_morph_normals = 0
2574
- base = 'morphNormal'
2575
-
2576
- @max_morph_normals.times do |i|
2577
- id = base + i
2578
- if attributes[id] >= 0
2579
- material.num_supported_morph_normals += 1
2580
- end
2581
- end
2582
- end
2583
-
2584
- material[:uniforms_list] = []
2585
-
2586
- material[:_opengl_shader][:uniforms].each_key do |u|
2587
- location = material.program.uniforms[u]
2588
-
2589
- if location
2590
- material[:uniforms_list] << [material[:_opengl_shader][:uniforms][u], location]
2591
- end
2592
- end
2593
- end
2594
-
2595
- def allocate_lights(lights)
2596
- dir_lights = 0
2597
- point_lights = 0
2598
- spot_lights = 0
2599
- hemi_lights = 0
2600
-
2601
- lights.each do |light|
2602
- next if light.only_shadow || !light.visible
2603
-
2604
- dir_lights += 1 if light.is_a? DirectionalLight
2605
- point_lights += 1 if light.is_a? PointLight
2606
- spot_lights += 1 if light.is_a? SpotLight
2607
- hemi_lights += 1 if light.is_a? HemisphereLight
2608
- end
2609
-
2610
- {
2611
- directional: dir_lights,
2612
- point: point_lights,
2613
- spot: spot_lights,
2614
- hemi: hemi_lights
2615
- }
2616
- end
2617
-
2618
- def allocate_shadows(lights)
2619
- max_shadows = 0
2620
-
2621
- lights.each do |light|
2622
- next unless light.cast_shadow
2623
-
2624
- max_shadows += 1 if light.is_a?(SpotLight)
2625
- max_shadows += 1 if light.is_a?(DirectionalLight) && !light.shadow_cascade
2626
- end
2627
-
2628
- max_shadows
2629
- end
2630
-
2631
- def allocate_bones(object = nil)
2632
- if @_supports_bone_textures && object && object.skeleton && object.skeleton.use_vertex_texture
2633
- return 1024
2634
- end
2635
-
2636
- # default for when object is not specified
2637
- # ( for example when prebuilding shader
2638
- # to be used with multiple objects )
2639
- #
2640
- # - leave some extra space for other uniforms
2641
- # - limit here is ANGLE's 254 max uniform vectors
2642
- # (up to 54 should be safe)
2643
-
2644
- n_vertex_uniforms = (get_gl_parameter(GL_MAX_VERTEX_UNIFORM_COMPONENTS) / 4.0).floor
2645
- n_vertex_matrices = ((n_vertex_uniforms - 20) / 4.0).floor
2646
-
2647
- max_bones = n_vertex_matrices
2648
-
2649
- # TODO: when SkinnedMesh exists
2650
- # if !object.nil? && object.is_a?(SkinnedMesh)
2651
- # max_bones = [object.skeleton.bones.length, max_bones].min
2652
- #
2653
- # if max_bones < object.skeleton.bones.length
2654
- # puts "WARNING: OpenGLRenderer: too many bones - #{object.skeleton.bones.length}, this GPU supports just #{max_bones}"
2655
- # end
2656
- # end
2657
-
2658
- max_bones
2659
- end
2660
-
2661
- def refresh_uniforms_common(uniforms, material)
2662
-
2663
- uniforms['opacity'].value = material.opacity
2664
-
2665
- uniforms['diffuse'].value = material.color
2666
-
2667
- uniforms['map'].value = material.map
2668
- uniforms['lightMap'].value = material.light_map
2669
- uniforms['specularMap'].value = material.specular_map
2670
- uniforms['alphaMap'].value = material.alpha_map
2671
-
2672
- if material.bump_map
2673
- uniforms['bumpMap'].value = material.bump_map
2674
- uniforms['bumpScale'].value = material.bump_scale
2675
- end
2676
-
2677
- if material.normal_map
2678
- uniforms['normalMap'].value = material.normal_map
2679
- uniforms['normalScale'].value.copy( material.normal_scale )
559
+ # TODO: when skinning is implemented. Then also refactor
560
+ # if object.bind_matrix && !program_uniforms['bindMatrix'].nil?
561
+ # glUniformMatrix4fv(program_uniforms['bindMatrix'], GL_FALSE, object.bind_matrix.elements)
562
+ # end
563
+ #
564
+ # if object.bind_matrix_inverse && !program_uniforms['bindMatrixInverse'].nil?
565
+ # glUniformMatrix4fv(program_uniforms['bindMatrixInverse'], GL_FALSE, object.bind_matrix_inverse.elements)
566
+ # end
567
+ #
568
+ # if @_supports_bone_textures && object.skeleton && object.skeleton.use_vertex_texture
569
+ # if !program_uniforms['boneTexture'].nil?
570
+ # texture_unit = get_texture_unit
571
+ #
572
+ # glUniform1i(program_uniforms['boneTexture'], texture_unit)
573
+ # object.skeleton.bone_texture.implementation(self).set(texture_unit)
574
+ # end
575
+ #
576
+ # if !program_uniforms['boneTextureWidth'].nil?
577
+ # glUniform1i(program_uniforms['boneTextureWidth'], object.skeleton.bone_texture_width)
578
+ # end
579
+ #
580
+ # if !program_uniforms['boneTextureHeight'].nil?
581
+ # glUniform1i(program_uniforms['boneTextureHeight'], object.skeleton.bone_texture_height)
582
+ # end
583
+ # elsif object.skeleton && object.skeleton.bone_matrices
584
+ # if !program_uniforms['boneGlobalMatrices'].nil?
585
+ # glUniformMatrix4fv(program_uniforms['boneGlobalMatrices'], GL_FALSE, object.skeleton.bone_matrices)
586
+ # end
587
+ # end
2680
588
  end
2681
589
 
2682
- # uv repeat and offset setting priorities
2683
- # 1. color map
2684
- # 2. specular map
2685
- # 3. normal map
2686
- # 4. bump map
2687
- # 5. alpha map
2688
-
2689
- uv_scale_map = nil
2690
-
2691
- if material.map
2692
- uv_scale_map = material.map
2693
- elsif material.specular_map
2694
- uv_scale_map = material.specular_map
2695
- elsif material.normal_map
2696
- uv_scale_map = material.normal_map
2697
- elsif material.bump_map
2698
- uv_scale_map = material.bump_map
2699
- elsif material.alpha_map
2700
- uv_scale_map = material.alpha_map
2701
- end
590
+ if refresh_material
591
+ # TODO: when fog is implemented
592
+ # refresh_uniforms_fog(material_uniforms, fog) if fog && material.fog
2702
593
 
2703
- if !uv_scale_map.nil?
2704
- offset = uv_scale_map.offset
2705
- repeat = uv_scale_map.repeat
594
+ if material_impl.needs_lights?
595
+ if @light_renderer.lights_need_update
596
+ refresh_lights = true
597
+ @light_renderer.setup(lights)
598
+ end
2706
599
 
2707
- uniforms['offsetRepeat'].value.set(offset.x, offset.y, repeat.x, repeat.y)
2708
- end
600
+ if refresh_lights
601
+ OpenGLHelper.refresh_uniforms_lights(material_uniforms, @light_renderer.cache)
602
+ end
2709
603
 
2710
- uniforms['envMap'].value = material.env_map
2711
- # TODO: when OpenGLRenderTargetCube exists
2712
- # uniforms['flipEnvMap'].value = material.envMap.is_a?(OpenGLRenderTargetCube) ? 1 : - 1
604
+ OpenGLHelper.mark_uniforms_lights_needs_update(material_uniforms, refresh_lights)
605
+ end
2713
606
 
2714
- uniforms['reflectivity'].value = material.reflectivity
2715
- uniforms['refractionRatio'].value = material.refraction_ratio
2716
- end
607
+ material_impl.refresh_uniforms(material_uniforms)
2717
608
 
2718
- def refresh_uniforms_phong(uniforms, material)
2719
- uniforms['shininess'].value = material.shininess
609
+ # TODO: when all of these things exist
610
+ # when LineDashedMaterial
611
+ # refresh_uniforms_line(material_uniforms, material)
612
+ # refresh_uniforms_dash(material_uniforms, material)
613
+ # when PointCloudMaterial
614
+ # refresh_uniforms_particle(material_uniforms, material)
615
+ # when MeshDepthMaterial
616
+ # material_uniforms.m_near.value = camera.near
617
+ # material_uniforms.m_far.value = camera.far
618
+ # material_uniforms.opacity.value = material.opacity
619
+ # when MeshNormalMaterial
620
+ # material_uniforms.opactity.value = material.opacity
2720
621
 
2721
- uniforms['emissive'].value = material.emissive
2722
- uniforms['specular'].value = material.specular
622
+ if object.receive_shadow && !material_impl.shadow_pass
623
+ OpenGLHelper.refresh_uniforms_shadow(material_uniforms, lights)
624
+ end
2723
625
 
2724
- if material.wrap_around
2725
- uniforms['wrapRGB'].value.copy(material.wrap_rgb)
626
+ load_uniforms_generic(material_impl.uniforms_list)
2726
627
  end
2727
- end
2728
-
2729
- def refresh_uniforms_shadow(uniforms, lights)
2730
- if uniforms['shadowMatrix']
2731
- lights.select(&:cast_shadow).select { |light|
2732
- light.is_a?(SpotLight) || (light.is_a?(DirectionalLight) && !light.shadow_cascade)
2733
- }.each_with_index { |light, i|
2734
- uniforms['shadowMap'].value[i] = light.shadow_map
2735
- uniforms['shadowMapSize'].value[i] = light.shadow_map_size
2736
628
 
2737
- uniforms['shadowMatrix'].value[i] = light.shadow_matrix
629
+ object.implementation(self).load_uniforms_matrices(program_uniforms)
2738
630
 
2739
- uniforms['shadowDarkness'].value[i] = light.shadow_darkness
2740
- uniforms['shadowBias'].value[i] = light.shadow_bias
2741
- }
631
+ if !program_uniforms['modelMatrix'].nil?
632
+ glUniformMatrix4fv(program_uniforms['modelMatrix'], 1, GL_FALSE, array_to_ptr_easy(object.matrix_world.elements))
2742
633
  end
2743
- end
2744
634
 
2745
- def refresh_uniforms_line(uniforms, material)
2746
- uniforms['diffuse'].value = material.color
2747
- uniforms['opacity'].value = material.opacity
635
+ program
2748
636
  end
2749
637
 
638
+ # FIXME: REFACTOR!?!?!?!?!???
639
+ # MASSIVE CASE STATEMENT OMG!!!
2750
640
  def load_uniforms_generic(uniforms)
2751
641
  uniforms.each do |(uniform, location)|
2752
642
  # needs_update property is not added to all uniforms.
@@ -2755,131 +645,84 @@ module Mittsu
2755
645
  type = uniform.type
2756
646
  value = uniform.value
2757
647
 
648
+ # AAAAAHHHHH!!!!! \o/ *flips table*
2758
649
  case type
2759
- when :'1i'
650
+ when :int
2760
651
  glUniform1i(location, value)
2761
- when :'1f'
652
+ when :ivec2
653
+ glUniform2i(location, value[0], value[1])
654
+ when :ivec3
655
+ glUniform3i(location, value[0], value[1], value[2])
656
+ when :ivec4
657
+ glUniform4i(location, value[0], value[1], value[2], value[3])
658
+ when :float
2762
659
  glUniform1f(location, value)
2763
- when :'2f'
660
+ when :vec2
2764
661
  glUniform2f(location, value[0], value[1])
2765
- when :'3f'
2766
- glUniform2f(location, value[0], value[1], value[2])
2767
- when :'4f'
662
+ when :vec3, :color
663
+ glUniform3f(location, value[0], value[1], value[2])
664
+ when :vec4
2768
665
  glUniform4f(location, value[0], value[1], value[2], value[3])
2769
- when :'1iv'
666
+ when :'int[]'
2770
667
  glUniform1iv(location, value.length, array_to_ptr_easy(value))
2771
- when :'2iv'
668
+ when :'ivec2[]'
2772
669
  glUniform2iv(location, value.length / 2, array_to_ptr_easy(value))
2773
- when :'3iv'
2774
- glUniform3iv(location, value.length / 3, array_to_ptr_easy(value))
2775
- when :'4iv'
2776
- glUniform3iv(location, value.length / 4, array_to_ptr_easy(value))
2777
- when :'1fv'
2778
- glUniform1fv(location, value.length, array_to_ptr_easy(value))
2779
- when :'2fv'
2780
- glUniform2fv(location, value.length / 2, array_to_ptr_easy(value))
2781
- when :'3fv'
2782
- glUniform3fv(location, value.length / 3, array_to_ptr_easy(value))
2783
- when :'4fv'
2784
- glUniform3fv(location, value.length / 4, array_to_ptr_easy(value))
2785
- when :Matrix3fv
2786
- glUniformMatrix3fv(location, value / 9, GL_FALSE, array_to_ptr_easy(value))
2787
- when :Matrix4fv
2788
- glUniformMatrix4fv(location, value / 16, GL_FALSE, array_to_ptr_easy(value))
2789
-
2790
- #
2791
-
2792
- when :i
2793
- # single integer
2794
- glUniform1i(location, value)
2795
- when :f
2796
- # single float
2797
- glUniform1f(location, value)
2798
- when :v2
2799
- # single Mittsu::Vector2
2800
- glUniform2f(location, value.x, value.y)
2801
- when :v3
2802
- # single Mittsu::Vector3
2803
- glUniform3f(location, value.x, value.y, value.z)
2804
- when :v4
2805
- # single Mittsu::Vector4
2806
- glUniform4f(location, value.x, value.y, value.z, value.w)
2807
- when :c
2808
- # single Mittsu::Color
2809
- glUniform3f(location, value.r, value.g, value.b)
2810
- when :iv1
2811
- # flat array of integers
2812
- glUniform1iv(location, value.length, array_to_ptr_easy(value))
2813
- when :iv
2814
- # flat array of integers with 3 x N size
670
+ when :'ivec3[]'
2815
671
  glUniform3iv(location, value.length / 3, array_to_ptr_easy(value))
2816
- when :fv1
2817
- # flat array of floats
672
+ when :'ivec4[]'
673
+ glUniform4iv(location, value.length / 4, array_to_ptr_easy(value))
674
+ when :'float[]'
2818
675
  glUniform1fv(location, value.length, array_to_ptr_easy(value))
2819
- when :fv
2820
- # flat array of float with 3 x N size
2821
- glUniform3fv(location, value.length / 3, array_to_ptr_easy(value))
2822
- when :v2v
2823
- # array of Mittsu::Vector2
2824
- uniform[:_array] ||= Array.new(2 * value.length) # Float32Array
2825
-
2826
- value.each_with_index do |v, i|
2827
- offset = i * 2
2828
- uniform[:_array][offset] = v.x
2829
- uniform[:_array][offset + 1] = v.y
676
+ when :'vec2[]'
677
+ if value[0].is_a? Vector2
678
+ uniform.array ||= value.flat_map(&:to_a) # TODO: Float32Array
679
+ glUniform2fv(location, value.length, array_to_ptr_easy(uniform.array))
680
+ else
681
+ glUniform2fv(location, value.length / 2, array_to_ptr_easy(value))
2830
682
  end
2831
-
2832
- glUniform2fv(location, value.length * 2, array_to_ptr_easy(uniform[:_array]))
2833
- when :v3v
2834
- # array of Mittsu::Vector3
2835
- uniform[:_array] ||= Array.new(3 * value.length) # Float32Array
2836
-
2837
- value.each_with_index do |v, i|
2838
- offset = i * 3
2839
- uniform[:_array][offset] = v.x
2840
- uniform[:_array][offset + 1] = v.y
2841
- uniform[:_array][offset + 2] = v.z
683
+ when :'vec3[]', :'color[]'
684
+ if value.first.is_a?(Vector3) || value.first.is_a?(Color)
685
+ uniform.array ||= value.flat_map(&:to_a) # TODO: Float32Array
686
+ glUniform3fv(location, value.length, array_to_ptr_easy(uniform.array))
687
+ else
688
+ glUniform3fv(location, value.length / 3, array_to_ptr_easy(value))
2842
689
  end
2843
-
2844
- glUniform3fv(location, value.length * 3, array_to_ptr_easy(uniform[:_array]))
2845
- when :v4v
2846
- # array of Mittsu::Vector4
2847
- uniform[:_array] ||= Array.new(4 * value.length) # Float32Array
2848
-
2849
- value.each_with_index do |v, i|
2850
- offset = i * 4
2851
- uniform[:_array][offset] = v.x
2852
- uniform[:_array][offset + 1] = v.y
2853
- uniform[:_array][offset + 2] = v.z
2854
- uniform[:_array][offset + 3] = v.w
690
+ when :'vec4[]'
691
+ if value.first.is_a? Vector4
692
+ uniform.array ||= value.flat_map(&:to_a) # TODO: Float32Array
693
+ glUniform4fv(location, value.length, array_to_ptr_easy(uniform.array))
694
+ else
695
+ glUniform4fv(location, value.length / 4, array_to_ptr_easy(value))
2855
696
  end
697
+ when :mat3
698
+ glUniformMatrix3fv(location, 1, GL_FALSE, array_to_ptr_easy(value.to_a))
699
+ when :mat4
700
+ glUniformMatrix4fv(location, 1, GL_FALSE, array_to_ptr_easy(value.to_a))
701
+ when :'mat3[]'
702
+ if value.first.is_a? Matrix3
703
+ uniform.array ||= Array.new(9 * value.length) # Float32Array
704
+
705
+ value.each_with_index do |v, i|
706
+ value[i].flatten_to_array_offset(uniform.array, i * 9)
707
+ end
2856
708
 
2857
- glUniform4fv(location, value.length * 4, array_to_ptr_easy(uniform[:_array]))
2858
- when :m3
2859
- # single Mittsu::Matrix3
2860
- glUniformMatrix3fv(location, 1, GL_FALSE, array_to_ptr_easy(value.elements))
2861
- when :m3v
2862
- # array of Mittsu::Matrix3
2863
- uniform[:_array] ||= Array.new(9 * value.length) # Float32Array
2864
-
2865
- value.each_with_index do |v, i|
2866
- value[i].flatten_to_array_offset(uniform[:_array], i * 9)
709
+ glUniformMatrix3fv(location, value.length, GL_FALSE, array_to_ptr_easy(uniform.array))
710
+ else
711
+ glUniformMatrix3fv(location, value.length / 9, GL_FALSE, array_to_ptr_easy(value))
2867
712
  end
713
+ when :'mat4[]'
714
+ if value.first.is_a? Matrix4
715
+ uniform.array ||= Array.new(16 * value.length) # Float32Array
2868
716
 
2869
- glUniformMatrix3fv(location, value.length, GL_FALSE, array_to_ptr_easy(uniform[:_array]))
2870
- when :m4
2871
- # single Mittsu::Matrix4
2872
- glUniformMatrix4vf(location, 1, GL_FALSE, array_to_ptr_easy(value.elements))
2873
- when :m4v
2874
- # array of Mittsu::Matrix4
2875
- uniform[:_array] ||= Array.new(16 * value.length) # Float32Array
717
+ value.each_with_index do |v, i|
718
+ value[i].flatten_to_array_offset(uniform.array, i * 16)
719
+ end
2876
720
 
2877
- value.each_with_index do |v, i|
2878
- value[i].flatten_to_array_offset(uniform[:_array], i * 16)
721
+ glUniformMatrix4fv(location, value.length, GL_FALSE, array_to_ptr_easy(uniform.array))
722
+ else
723
+ glUniformMatrix4fv(location, value.length / 16, GL_FALSE, array_to_ptr_easy(value))
2879
724
  end
2880
-
2881
- glUniformMatrix4fv(location, value.length, GL_FALSE, array_to_ptr_easy(uniform[:_array]))
2882
- when :t
725
+ when :texture
2883
726
  # single Mittsu::Texture (2d or cube)
2884
727
  texture = value
2885
728
  texture_unit = get_texture_unit
@@ -2888,30 +731,27 @@ module Mittsu
2888
731
 
2889
732
  next unless texture
2890
733
 
2891
- if texture.is_a?(CubeTexture) || (texture.is_a?(Array) && texture.image.length == 6)
2892
- set_cube_texture(texture, texture_unit)
734
+ texture_impl = texture.implementation(self)
735
+ texture_impl.set(texture_unit)
2893
736
  # TODO: when OpenGLRenderTargetCube is defined
2894
737
  # elsif texture.is_a?(OpenGLRenderTargetCube)
2895
738
  # set_cube_texture_dynamic(texture, texture_unit)
2896
- else
2897
- set_texture(texture, texture_unit)
2898
- end
2899
- when :tv
739
+ when :'texture[]'
2900
740
  # array of Mittsu::Texture (2d)
2901
- uniform[:_array] ||= []
741
+ uniform.array ||= []
2902
742
 
2903
743
  uniform.value.each_index do |i|
2904
- uniform[:_array][i] = get_texture_unit
744
+ uniform.array[i] = get_texture_unit
2905
745
  end
2906
746
 
2907
- glUniform1iv(location, uniform[:_array].length, array_to_ptr_easy(uniform[:_array]))
747
+ glUniform1iv(location, uniform.array.length, array_to_ptr_easy(uniform.array))
2908
748
 
2909
749
  uniform.value.each_with_index do |tex, i|
2910
- tex_unit = uniform[:_array][i]
750
+ tex_unit = uniform.array[i]
2911
751
 
2912
752
  next unless tex
2913
753
 
2914
- set_texture(tex, tex_unit)
754
+ tex.implementation(self).set(tex_unit)
2915
755
  end
2916
756
  else
2917
757
  puts "WARNING: Mittsu::OpenGLRenderer: Unknown uniform type: #{type}"
@@ -2919,457 +759,292 @@ module Mittsu
2919
759
  end
2920
760
  end
2921
761
 
2922
- def load_uniforms_matrices(uniforms, object)
2923
- glUniformMatrix4fv(uniforms['modelViewMatrix'], 1, GL_FALSE, array_to_ptr_easy(object[:_model_view_matrix].elements))
762
+ def get_texture_unit
763
+ texture_unit = @_used_texture_units
2924
764
 
2925
- if uniforms['normalMatrix']
2926
- glUniformMatrix3fv(uniforms['normalMatrix'], 1, GL_FALSE, array_to_ptr_easy(object[:_normal_matrix].elements))
765
+ if texture_unit >= @_max_textures
766
+ puts "WARNING: OpenGLRenderer: trying to use #{texture_unit} texture units while this GPU supports only #{@_max_textures}"
2927
767
  end
2928
- end
2929
-
2930
- def setup_lights(lights)
2931
- r, g, b = 0.0, 0.0, 0.0
2932
-
2933
- zlights = @_lights
2934
-
2935
- dir_colors = zlights[:directional][:colors]
2936
- dir_positions = zlights[:directional][:positions]
2937
-
2938
- point_colors = zlights[:point][:colors]
2939
- point_positions = zlights[:point][:positions]
2940
- point_distances = zlights[:point][:distances]
2941
- point_decays = zlights[:point][:decays]
2942
-
2943
- spot_colors = zlights[:spot][:colors]
2944
- spot_positions = zlights[:spot][:positions]
2945
- spot_distances = zlights[:spot][:distances]
2946
- spot_directions = zlights[:spot][:directions]
2947
- spot_angles_cos = zlights[:spot][:angles_cos]
2948
- spot_exponents = zlights[:spot][:exponents]
2949
- spot_decays = zlights[:spot][:decays]
2950
-
2951
- hemi_sky_colors = zlights[:hemi][:sky_colors]
2952
- hemi_ground_colors = zlights[:hemi][:ground_colors]
2953
- hemi_positions = zlights[:hemi][:positions]
2954
768
 
2955
- dir_length = 0
2956
- point_length = 0
2957
- spot_length = 0
2958
- hemi_length = 0
2959
-
2960
- dir_count = 0
2961
- point_count = 0
2962
- spot_count = 0
2963
- hemi_count = 0
2964
-
2965
- dir_offset = 0
2966
- point_offset = 0
2967
- spot_offset = 0
2968
- hemi_offset = 0
2969
-
2970
- lights.each do |light|
2971
-
2972
- next if light.only_shadow
2973
-
2974
- color = light.color
2975
- intensity = light.intensity
2976
- distance = light.distance
2977
-
2978
- if light.is_a? AmbientLight
2979
-
2980
- next unless light.visible
2981
-
2982
- r += color.r
2983
- g += color.g
2984
- b += color.b
2985
-
2986
- elsif light.is_a? DirectionalLight
2987
-
2988
- dir_count += 1
2989
-
2990
- next unless light.visible
2991
-
2992
- @_direction.set_from_matrix_position(light.matrix_world)
2993
- @_vector3.set_from_matrix_position(light.target.matrix_world)
2994
- @_direction.sub(@_vector3)
2995
- @_direction.normalize
2996
-
2997
- dir_offset = dir_length * 3
2998
-
2999
- dir_positions[dir_offset] = @_direction.x
3000
- dir_positions[dir_offset + 1] = @_direction.y
3001
- dir_positions[dir_offset + 2] = @_direction.z
3002
-
3003
- set_color_linear(dir_colors, dir_offset, color, intensity)
3004
-
3005
- dir_length += 1
3006
-
3007
- elsif light.is_a? PointLight
3008
-
3009
- point_count += 1
3010
-
3011
- next unless light.visible
3012
-
3013
- point_offset = point_length * 3;
3014
-
3015
- set_color_linear(point_colors, point_offset, color, intensity)
3016
-
3017
- @_vector3.set_from_matrix_position(light.matrix_world)
3018
-
3019
- point_positions[point_offset] = @_vector3.x
3020
- point_positions[point_offset + 1] = @_vector3.y
3021
- point_positions[point_offset + 2] = @_vector3.z
3022
-
3023
- # distance is 0 if decay is 0, because there is no attenuation at all.
3024
- point_distances[point_length] = distance
3025
- point_decays[point_length] = light.distance.zero? ? 0.0 : light.decay
3026
-
3027
- point_length += 1
3028
-
3029
- elsif light.is_a? SpotLight
3030
-
3031
- spot_count += 1
3032
-
3033
- next unless light.visible
3034
-
3035
- spot_offset = spot_length * 3
3036
-
3037
- set_color_linear(spot_colors, spot_offset, color, intensity)
3038
-
3039
- @_direction.set_from_matrix_position(light.matrix_world)
3040
-
3041
- spot_positions[spot_offset] = @_direction.x
3042
- spot_positions[spot_offset + 1] = @_direction.y
3043
- spot_positions[spot_offset + 2] = @_direction.z
3044
-
3045
- spot_distances[spot_length] = distance
3046
-
3047
- @_vector3.set_from_matrix_position(light.target.matrix_world)
3048
- @_direction.sub(@_vector3)
3049
- @_direction.normalize
3050
-
3051
- spot_directions[spot_offset] = @_direction.x
3052
- spot_directions[spot_offset + 1] = @_direction.y
3053
- spot_directions[spot_offset + 2] = @_direction.z
3054
-
3055
- spot_angles_cos[spot_length] = Math.cos(light.angle)
3056
- spot_exponents[spot_length] = light.exponent;
3057
- spot_decays[spot_length] = light.distance.zero? ? 0.0 : light.decay
3058
-
3059
- spot_length += 1;
769
+ @_used_texture_units += 1
770
+ texture_unit
771
+ end
3060
772
 
3061
- elsif light.is_a? HemisphereLight
773
+ def ensure_depth_buffer_writing
774
+ @state.set_depth_test(true)
775
+ @state.set_depth_write(true)
776
+ @state.set_color_write(true)
777
+ end
3062
778
 
3063
- hemi_count += 1
779
+ def reset_cache
780
+ @_current_geometry_program = ''
781
+ @_current_material_id = -1
782
+ @_current_camera = nil
783
+ @light_renderer.reset
784
+ end
3064
785
 
3065
- next unless light.visible
786
+ def reset_objects_cache
787
+ @lights.clear
788
+ @opaque_objects.clear
789
+ @transparent_objects.clear
790
+ @sprites.clear
791
+ @lens_flares.clear
792
+ end
3066
793
 
3067
- @_direction.set_from_matrix_position(light.matrix_world)
3068
- @_direction.normalize
794
+ def reset_info
795
+ @info[:render][:calls] = 0
796
+ @info[:render][:vertices] = 0
797
+ @info[:render][:faces] = 0
798
+ @info[:render][:points] = 0
799
+ end
3069
800
 
3070
- hemi_offset = hemi_length * 3
801
+ def reset_cache_for_this_frame
802
+ reset_cache
803
+ reset_objects_cache
804
+ reset_info
805
+ end
3071
806
 
3072
- hemi_positions[hemi_offset] = @_direction.x
3073
- hemi_positions[hemi_offset + 1] = @_direction.y
3074
- hemi_positions[hemi_offset + 2] = @_direction.z
807
+ def update_screen_projection(camera)
808
+ camera.matrix_world_inverse.inverse(camera.matrix_world)
3075
809
 
3076
- sky_color = light.color
3077
- ground_color = light.ground_color
810
+ @proj_screen_matrix.multiply_matrices(camera.projection_matrix, camera.matrix_world_inverse)
811
+ @_frustum.set_from_matrix(@proj_screen_matrix)
812
+ end
3078
813
 
3079
- set_color_linear(hemi_sky_colors, hemi_offset, sky_color, intensity )
3080
- set_color_linear(hemi_ground_colors, hemi_offset, ground_color, intensity)
814
+ def sort_objects_for_render
815
+ @opaque_objects.sort { |a,b| OpenGLHelper.painter_sort_stable(a,b) }
816
+ @transparent_objects.sort { |a,b| OpenGLHelper.reverse_painter_sort_stable(a,b) }
817
+ end
3081
818
 
3082
- hemi_length += 1
819
+ def set_matrices_for_immediate_objects(camera)
820
+ @_opengl_objects_immediate.each do |opengl_object|
821
+ object = opengl_object.object
3083
822
 
823
+ if object.visible
824
+ object.implementation(self).setup_matrices(camera)
825
+ unroll_immediate_buffer_material(opengl_object)
3084
826
  end
3085
-
3086
827
  end
828
+ end
3087
829
 
3088
- # null eventual remains from removed lights
3089
- # (this is to avoid if in shader)
830
+ def render_main_pass(scene, camera)
831
+ if scene.override_material
832
+ render_with_override_material(scene, camera)
833
+ else
834
+ render_with_default_materials(scene, camera)
835
+ end
836
+ end
3090
837
 
3091
- (dir_length * 3).upto([dir_colors.length, dir_count * 3].max - 1).each { |i|
3092
- dir_colors[i] = 0.0
3093
- }
3094
- (point_length * 3).upto([point_colors.length, point_count * 3].max - 1).each { |i|
3095
- point_colors[i] = 0.0
3096
- }
3097
- (spot_length * 3).upto([spot_colors.length, spot_count * 3].max - 1).each { |i|
3098
- spot_colors[i] = 0.0
3099
- }
3100
- (hemi_length * 3).upto([hemi_ground_colors.length, hemi_count * 3].max - 1).each { |i|
3101
- hemi_ground_colors[i] = 0.0
3102
- }
3103
- (hemi_length * 3).upto([hemi_sky_colors.length, hemi_count * 3].max - 1).each { |i|
3104
- hemi_sky_colors[i] = 0.0
3105
- }
838
+ def render_with_override_material(scene, camera)
839
+ override_material = scene.override_material
840
+ material_impl = override_material.implementation(self)
3106
841
 
3107
- zlights[:directional][:length] = dir_length
3108
- zlights[:point][:length] = point_length
3109
- zlights[:spot][:length] = spot_length
3110
- zlights[:hemi][:length] = hemi_length
842
+ material_impl.set
3111
843
 
3112
- zlights[:ambient][0] = r
3113
- zlights[:ambient][1] = g
3114
- zlights[:ambient][2] = b
844
+ render_objects(@opaque_objects, camera, @lights, scene.fog, override_material)
845
+ render_objects(@transparent_objects, camera, @lights, scene.fog, override_material)
846
+ render_objects_immediate(@_opengl_objects_immediate, nil, camera, @lights, scene.fog, override_material)
3115
847
  end
3116
848
 
3117
- def refresh_uniforms_lights(uniforms, lights)
3118
- uniforms['ambientLightColor'].value = lights[:ambient]
849
+ def render_with_default_materials(scene, camera)
850
+ render_opaque_pass(scene, camera)
851
+ render_transparent_pass(scene, camera)
852
+ end
3119
853
 
3120
- uniforms['directionalLightColor'].value = lights[:directional][:colors]
3121
- uniforms['directionalLightDirection'].value = lights[:directional][:positions]
854
+ def render_opaque_pass(scene, camera)
855
+ # front-to-back order
856
+ @state.set_blending(NoBlending)
3122
857
 
3123
- uniforms['pointLightColor'].value = lights[:point][:colors]
3124
- uniforms['pointLightPosition'].value = lights[:point][:positions]
3125
- uniforms['pointLightDistance'].value = lights[:point][:distances]
3126
- uniforms['pointLightDecay'].value = lights[:point][:decays]
858
+ render_objects(@opaque_objects, camera, @lights, scene.fog, nil)
859
+ render_objects_immediate(@_opengl_objects_immediate, :opaque, camera, @lights, scene.fog, nil)
860
+ end
3127
861
 
3128
- uniforms['spotLightColor'].value = lights[:spot][:colors]
3129
- uniforms['spotLightPosition'].value = lights[:spot][:positions]
3130
- uniforms['spotLightDistance'].value = lights[:spot][:distances]
3131
- uniforms['spotLightDirection'].value = lights[:spot][:directions]
3132
- uniforms['spotLightAngleCos'].value = lights[:spot][:angles_cos]
3133
- uniforms['spotLightExponent'].value = lights[:spot][:exponents]
3134
- uniforms['spotLightDecay'].value = lights[:spot][:decays]
862
+ def render_transparent_pass(scene, camera)
863
+ # back-to-front-order
864
+ render_objects(@transparent_objects, camera, @lights, scene.fog, nil)
865
+ render_objects_immediate(@_opengl_objects_immediate, :transparent, camera, @lights, scene.fog, nil)
866
+ end
3135
867
 
3136
- uniforms['hemisphereLightSkyColor'].value = lights[:hemi][:sky_colors]
3137
- uniforms['hemisphereLightGroundColor'].value = lights[:hemi][:ground_colors]
3138
- uniforms['hemisphereLightDirection'].value = lights[:hemi][:positions]
868
+ def render_custom_plugins_pre_pass(scene, camera)
869
+ @shadow_map_plugin.render(scene, camera)
3139
870
  end
3140
871
 
3141
- def mark_uniforms_lights_needs_update(uniforms, value)
3142
- uniforms['ambientLightColor'].needs_update = value
872
+ def render_custom_plugins_post_pass(scene, camera)
873
+ # TODO: when these custom plugins are implemented
874
+ # @sprite_plugin.render(scene, camera)
875
+ # lens_flare_plugin.render(scene, camera, @_current_render_target.width, @_current_render_target.height)
876
+ end
3143
877
 
3144
- uniforms['directionalLightColor'].needs_update = value
3145
- uniforms['directionalLightDirection'].needs_update = value
878
+ def update_skeleton_objects(scene)
879
+ # TODO: when SkinnedMesh is defined
880
+ # scene.traverse do |object|
881
+ # if object.is_a? SkinnedMesh
882
+ # object.skeleton.update
883
+ # end
884
+ # end
885
+ end
3146
886
 
3147
- uniforms['pointLightColor'].needs_update = value
3148
- uniforms['pointLightPosition'].needs_update = value
3149
- uniforms['pointLightDistance'].needs_update = value
3150
- uniforms['pointLightDecay'].needs_update = value
887
+ def perform_auto_clear
888
+ clear(@auto_clear_color, @auto_clear_depth, @auto_clear_stencil)
889
+ end
3151
890
 
3152
- uniforms['spotLightColor'].needs_update = value
3153
- uniforms['spotLightPosition'].needs_update = value
3154
- uniforms['spotLightDistance'].needs_update = value
3155
- uniforms['spotLightDirection'].needs_update = value
3156
- uniforms['spotLightAngleCos'].needs_update = value
3157
- uniforms['spotLightExponent'].needs_update = value
3158
- uniforms['spotLightDecay'].needs_update = value
891
+ def init_clearing
892
+ @_clear_color = Color.new(0x000000)
893
+ @_clear_alpha = 0.0
3159
894
 
3160
- uniforms['hemisphereLightSkyColor'].needs_update = value
3161
- uniforms['hemisphereLightGroundColor'].needs_update = value
3162
- uniforms['hemisphereLightDirection'].needs_update = value
895
+ @auto_clear = true
896
+ @auto_clear_color = true
897
+ @auto_clear_depth = true
898
+ @auto_clear_stencil = true
3163
899
  end
3164
900
 
3165
- def refresh_uniforms_lambert(uniforms, material)
3166
- uniforms['emissive'].value = material.emissive
901
+ def init_gamma
902
+ @gamma_factor = 2.0 # backwards compat???
903
+ @gamma_input = false
904
+ @gamma_output = false
905
+ end
3167
906
 
3168
- if material.wrap_around
3169
- uniforms['wrapRGB'].value.copy(material.wrap_rgb)
3170
- end
907
+ def init_shadow_properties
908
+ @shadow_map_enabled = false
909
+ @shadow_map_type = PCFShadowMap
910
+ @shadow_map_cull_face = CullFaceFront
911
+ @shadow_map_debug = false
912
+ @shadow_map_cascade = false
3171
913
  end
3172
914
 
3173
- def set_color_linear(array, offset, color, intensity)
3174
- array[offset] = color.r * intensity
3175
- array[offset + 1] = color.g * intensity
3176
- array[offset + 2] = color.b * intensity
915
+ def init_morphs
916
+ @max_morph_targets = 8
917
+ @max_morph_normals = 4
3177
918
  end
3178
919
 
3179
- def get_texture_unit
3180
- texture_unit = @_used_texture_units
920
+ def init_collections
921
+ @lights = []
3181
922
 
3182
- if texture_unit >= @_max_textures
3183
- puts "WARNING: OpenGLRenderer: trying to use #{texture_unit} texture units while this GPU supports only #{@_max_textures}"
3184
- end
923
+ @_opengl_objects = {}
924
+ @_opengl_objects_immediate = []
3185
925
 
3186
- @_used_texture_units += 1
3187
- texture_unit
3188
- end
926
+ @opaque_objects = []
927
+ @transparent_objects = []
3189
928
 
3190
- def clamp_to_max_size(image, max_size)
3191
- if image.width > max_size || image.height > max_size
3192
- # TODO: scale the image ...
929
+ @sprites = []
930
+ @lens_flares = []
3193
931
 
3194
- puts "WARNING: Mittsu::OpenGLRenderer: image is too big (#{image.width} x #{image.height}). Resized to ??? x ???"
3195
- end
3196
- image
932
+ @programs = []
3197
933
  end
3198
934
 
3199
- def param_mittsu_to_gl(p)
3200
- case p
3201
- when RepeatWrapping then GL_REPEAT
3202
- when ClampToEdgeWrapping then GL_CLAMP_TO_EDGE
3203
- when MirroredRepeatWrapping then GL_MIRRORED_REPEAT
3204
-
3205
- when NearestFilter then GL_NEAREST
3206
- when NearestMipMapNearestFilter then GL_NEAREST_MIPMAP_NEAREST
3207
- when NearestMipMapLinearFilter then GL_NEAREST_MIPMAP_LINEAR
3208
-
3209
- when LinearFilter then GL_LINEAR
3210
- when LinearMipMapNearestFilter then GL_LINEAR_MIPMAP_NEAREST
3211
- when LinearMipMapLinearFilter then GL_LINEAR_MIPMAP_LINEAR
3212
-
3213
- when UnsignedByteType then GL_UNSIGNED_BYTE
3214
- when UnsignedShort4444Type then GL_UNSIGNED_SHORT_4_4_4_4
3215
- when UnsignedShort5551Type then GL_UNSIGNED_SHORT_5_5_5_1
3216
- when UnsignedShort565Type then GL_UNSIGNED_SHORT_5_6_5
3217
-
3218
- when ByteType then GL_BYTE
3219
- when ShortType then GL_SHORT
3220
- when UnsignedShortType then GL_UNSIGNED_SHORT
3221
- when IntType then GL_INT
3222
- when UnsignedIntType then GL_UNSIGNED_INT
3223
- when FloatType then GL_FLOAT
3224
-
3225
- when AlphaFormat then GL_ALPHA
3226
- when RGBFormat then GL_RGB
3227
- when RGBAFormat then GL_RGBA
3228
- when LuminanceFormat then GL_LUMINANCE
3229
- when LuminanceAlphaFormat then GL_LUMINANCE_ALPHA
3230
-
3231
- when AddEquation then GL_FUNC_ADD
3232
- when SubtractEquation then GL_FUNC_SUBTRACT
3233
- when ReverseSubtractEquation then GL_FUNC_REVERSE_SUBTRACT
3234
-
3235
- when ZeroFactor then GL_ZERO
3236
- when OneFactor then GL_ONE
3237
- when SrcColorFactor then GL_SRC_COLOR
3238
- when OneMinusSrcColorFactor then GL_ONE_MINUS_SRC_COLOR
3239
- when SrcAlphaFactor then GL_SRC_ALPHA
3240
- when OneMinusSrcAlphaFactor then GL_ONE_MINUS_SRC_ALPHA
3241
- when DstAlphaFactor then GL_DST_ALPHA
3242
- when OneMinusDstAlphaFactor then GL_ONE_MINUS_DST_ALPHA
3243
-
3244
- when DstColorFactor then GL_DST_COLOR
3245
- when OneMinusDstColorFactor then GL_ONE_MINUS_DST_COLOR
3246
- when SrcAlphaSaturateFactor then GL_SRC_ALPHA_SATURATE
3247
- else 0
3248
- end
935
+ def init_info
936
+ @info = {
937
+ memory: {
938
+ programs: 0,
939
+ geometries: 0,
940
+ textures: 0
941
+ },
942
+ render: {
943
+ calls: 0,
944
+ vertices: 0,
945
+ faces: 0,
946
+ points: 0
947
+ }
948
+ }
3249
949
  end
3250
950
 
3251
- def set_texture_parameters(texture_type, texture, is_image_power_of_two)
3252
- if is_image_power_of_two
3253
- glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, param_mittsu_to_gl(texture.wrap_s))
3254
- glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, param_mittsu_to_gl(texture.wrap_t))
3255
-
3256
- glTexParameteri(texture_type, GL_TEXTURE_MAG_FILTER, param_mittsu_to_gl(texture.mag_filter))
3257
- glTexParameteri(texture_type, GL_TEXTURE_MIN_FILTER, param_mittsu_to_gl(texture.min_filter))
3258
- else
3259
- glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
3260
- glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
3261
-
3262
- if texture.wrap_s != ClampToEdgeWrapping || texture.wrap_t != ClampToEdgeWrapping
3263
- puts "WARNING: Mittsu::OpenGLRenderer: Texture is not power of two. Texture.wrap_s and Texture.wrap_t should be set to Mittsu::ClampToEdgeWrapping. (#{texture.source_file})"
3264
- end
3265
-
3266
- glTexParameteri(texture_type, GL_TEXTURE_MAG_FILTER, filter_fallback(texture.mag_filter))
3267
- glTexParameteri(texture_type, GL_TEXTURE_MIN_FILTER, filter_fallback(texture.min_filter))
951
+ def init_state_cache
952
+ @_current_program = nil
953
+ @_current_render_target = default_target
954
+ @_current_material_id = -1
955
+ @_current_geometry_program = ''
956
+ @_current_camera = nil
3268
957
 
3269
- if texture.min_filter != NearestFilter && texture.min_filter != LinearFilter
3270
- puts "WARNING: Mittsu::OpenGLRenderer: Texture is not a power of two. Texture.min_filter should be set to Mittsu::NearestFilter or Mittsu::LinearFilter. (#{texture.source_file})"
3271
- end
958
+ @_used_texture_units = 0
959
+ end
3272
960
 
3273
- # TODO: anisotropic extension ???
3274
- end
961
+ def init_camera_matrix_cache
962
+ @_frustum = Frustum.new
963
+ @proj_screen_matrix = Matrix4.new
964
+ @_vector3 = Vector3.new
3275
965
  end
3276
966
 
3277
- def set_cube_texture(texture, slot)
3278
- if texture.image.length == 6
3279
- if texture.needs_update?
3280
- if !texture.image[:_opengl_texture_cube]
3281
- texture.add_event_listener(:dispose, @on_texture_dispose)
3282
- texture.image[:_opengl_texture_cube] = glCreateTexture
3283
- @info[:memory][:textures] += 1
3284
- end
967
+ def fetch_parameters(parameters)
968
+ @_alpha = parameters.fetch(:alpha, false)
969
+ @_depth = parameters.fetch(:depth, true)
970
+ @_stencil = parameters.fetch(:stencil, true)
971
+ @_antialias = parameters.fetch(:antialias, false)
972
+ @_premultiplied_alpha = parameters.fetch(:premultiplied_alpha, true)
973
+ @_preserve_drawing_buffer = parameters.fetch(:preserve_drawing_buffer, false)
974
+ @logarithmic_depth_buffer = parameters.fetch(:logarithmic_depth_buffer, false)
3285
975
 
3286
- glActiveTexture(GL_TEXTURE0 + slot)
3287
- glBindTexture(GL_TEXTURE_CUBE_MAP, texture.image[:_opengl_texture_cube])
976
+ @width = parameters.fetch(:width, 800)
977
+ @height = parameters.fetch(:height, 600)
978
+ @title = parameters.fetch(:title, "Mittsu #{REVISION}")
979
+ end
3288
980
 
3289
- # glPixelStorei(GL_UNPACK_FLIP_Y_WEBGL, texture.flip_y)
981
+ def get_gpu_capabilities
982
+ @_max_textures = glGetParameter(GL_MAX_TEXTURE_IMAGE_UNITS)
983
+ @_max_vertex_textures = glGetParameter(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS)
984
+ @_max_texture_size = glGetParameter(GL_MAX_TEXTURE_SIZE)
985
+ @_max_cubemap_size = glGetParameter(GL_MAX_CUBE_MAP_TEXTURE_SIZE)
3290
986
 
3291
- is_compressed = texture.is_a?(CompressedTexture)
3292
- is_data_texture = texture.image[0].is_a?(DataTexture)
987
+ @_supports_vertex_textures = @_max_vertex_textures > 0
988
+ @_supports_bone_textures = @_supports_vertex_textures && false # TODO: extensions.get('OES_texture_float') ????
989
+ end
3293
990
 
3294
- cube_image = [];
991
+ def init_plugins
992
+ @shadow_map_plugin = ShadowMapPlugin.new(self, @lights, @_opengl_objects, @_opengl_objects_immediate)
3295
993
 
3296
- 6.times do |i|
3297
- if @auto_scale_cubemaps && !is_compressed && !is_data_texture
3298
- cube_image[i] = clamp_to_max_size(texture.image[i], @_max_cubemap_size)
3299
- else
3300
- cube_image[i] = is_data_texture ? texture.image[i].image : texture.image[i];
3301
- end
3302
- end
994
+ # TODO: when these custom plugins are implemented
995
+ # @sprite_plugin = SpritePlugin.new(self, @sprites)
996
+ # @lens_flare_plugin = LensFlarePlugin.new(self, @lens_flares)
997
+ end
3303
998
 
3304
- image = cube_image[0]
3305
- is_image_power_of_two = Math.power_of_two?(image.width) && Math.power_of_two?(image.height)
3306
- gl_format = param_mittsu_to_gl(texture.format)
3307
- gl_type = param_mittsu_to_gl(texture.type)
999
+ def create_window
1000
+ # attributes = {
1001
+ # alpha: _alpha,
1002
+ # depth: _depth,
1003
+ # stencil: _stencil,
1004
+ # antialias: _antialias,
1005
+ # premultiplied_alpha: _premultiplied_alpha,
1006
+ # preserve_drawing_buffer: _preserve_drawing_buffer
1007
+ # }
3308
1008
 
3309
- set_texture_parameters(GL_TEXTURE_CUBE_MAP, texture, is_image_power_of_two)
1009
+ @window = GLFW::Window.new(@width, @height, @title)
3310
1010
 
3311
- 6.times do |i|
3312
- if !is_compressed
3313
- if is_data_texture
3314
- glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, gl_format, cube_image[i].width, cube_image[i].height, 0, gl_format, gl_type, cube_image[i].data)
3315
- else
3316
- glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, gl_format, cube_image[i].width, cube_image[i].height, 0, gl_format, gl_type, cube_image[i].data)
3317
- end
3318
- else
3319
- mipmaps = cube_image[i].mipmaps
3320
-
3321
- mipmaps.each_with_index do |mipmap, j|
3322
- if texture.format != RGBAFormat && texture.format != RGBFormat
3323
- if get_compressed_texture_formats.include?(gl_format)
3324
- glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, j, gl_format, mipmap.width, mipmap.height, 0, mipmap.data)
3325
- else
3326
- puts "WARNING: Mittsu::OpenGLRenderer: Attempt to load unsupported compressed texture format in #set_cube_texture"
3327
- end
3328
- else
3329
- glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, j, gl_format, mipmap.width, mipmap.height, 0, gl_format, gl_type, mipmap.data)
3330
- end
3331
- end
3332
- end
3333
- end
1011
+ default_target.set_viewport_size(*(@window.framebuffer_size))
3334
1012
 
3335
- if texture.generate_mipmaps && is_image_power_of_two
3336
- glGenerateMipmap(GL_TEXTURE_CUBE_MAP)
3337
- end
1013
+ # TODO: handle losing opengl context??
1014
+ end
3338
1015
 
3339
- texture.needs_update = false
1016
+ def switch_geometry_program(program, material, geometry_group)
1017
+ wireframe_bit = material.wireframe ? 1 : 0
1018
+ geometry_program = "#{geometry_group.id}_#{program.id}_#{wireframe_bit}"
3340
1019
 
3341
- # TODO wat?
3342
- # texture.on_update if texture.on_update
3343
- else
3344
- glActiveTexture(GL_TEXTURE0 + slot)
3345
- glBindTexture(GL_TEXTURE_CUBE_MAP, texture.image[:_opengl_texture_cube])
3346
- end
1020
+ if geometry_program != @_current_geometry_program
1021
+ @_current_geometry_program = geometry_program
1022
+ true
1023
+ else
1024
+ false
3347
1025
  end
3348
1026
  end
3349
1027
 
3350
- def setup_framebuffer(framebuffer, render_target, texture_target)
3351
- glBindFramebuffer(GL_FRAMEBUFFER, framebuffer)
3352
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_target, render_target[:_opengl_texture], 0)
1028
+ def default_target
1029
+ @_defualt_target ||= OpenGLDefaultTarget.new(self)
3353
1030
  end
3354
1031
 
3355
- def setup_renderbuffer(renderbuffer, render_target)
3356
- glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer)
1032
+ def update_camera_uniforms(uniforms, camera, material)
1033
+ material_impl = material.implementation(self)
3357
1034
 
3358
- if render_target.depth_buffer && !render_target.stencil_buffer
3359
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, render_target.width, render_target.height)
3360
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer)
1035
+ glUniformMatrix4fv(uniforms['projectionMatrix'], 1, GL_FALSE, array_to_ptr_easy(camera.projection_matrix.elements))
3361
1036
 
3362
- # TODO: investigate this (?):
3363
- # THREE.js - For some reason this is not working. Defaulting to RGBA4.
3364
- # } else if ( ! renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
3365
- #
3366
- # _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.STENCIL_INDEX8, renderTarget.width, renderTarget.height );
3367
- # _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
3368
- elsif render_target.depth_buffer && render_target.stencil_buffer
3369
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, render_target.width, render_target.height)
3370
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderbuffer)
3371
- else
3372
- glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, render_target.width, render_target.height)
1037
+ if @logarithmic_depth_buffer
1038
+ glUniform1f(uniforms['logDepthBuffFC'], 2.0 / Math.log(camera.far + 1.0) / Math::LN2)
1039
+ end
1040
+
1041
+ if material_impl.needs_camera_position_uniform? && !uniforms['cameraPosition'].nil?
1042
+ @_vector3.set_from_matrix_position(camera.matrix_world)
1043
+ glUniform3f(uniforms['cameraPosition'], @_vector3.x, @_vector3.y, @_vector3.z)
1044
+ end
1045
+
1046
+ if material_impl.needs_view_matrix_uniform? && !uniforms['viewMatrix'].nil?
1047
+ glUniformMatrix4fv(uniforms['viewMatrix'], 1, GL_FALSE, array_to_ptr_easy(camera.matrix_world_inverse.elements))
3373
1048
  end
3374
1049
  end
3375
1050
  end