mittsu 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -1
  3. data/README.md +1 -1
  4. data/lib/mittsu/cameras/orthographic_camera.rb +13 -0
  5. data/lib/mittsu/cameras/perspective_camera.rb +11 -0
  6. data/lib/mittsu/core/geometry.rb +12 -9
  7. data/lib/mittsu/core/object_3d.rb +33 -66
  8. data/lib/mittsu/lights/ambient_light.rb +8 -0
  9. data/lib/mittsu/lights/directional_light.rb +9 -0
  10. data/lib/mittsu/lights/hemisphere_light.rb +9 -0
  11. data/lib/mittsu/lights/point_light.rb +11 -0
  12. data/lib/mittsu/lights/spot_light.rb +13 -0
  13. data/lib/mittsu/loaders.rb +1 -0
  14. data/lib/mittsu/loaders/mtl_loader.rb +5 -12
  15. data/lib/mittsu/loaders/obj_loader.rb +212 -0
  16. data/lib/mittsu/loaders/obj_mtl_loader.rb +11 -207
  17. data/lib/mittsu/materials/material.rb +5 -2
  18. data/lib/mittsu/materials/mesh_basic_material.rb +0 -9
  19. data/lib/mittsu/math/color.rb +44 -104
  20. data/lib/mittsu/math/matrix3.rb +8 -1
  21. data/lib/mittsu/math/matrix4.rb +6 -0
  22. data/lib/mittsu/math/vector.rb +251 -0
  23. data/lib/mittsu/math/vector2.rb +14 -213
  24. data/lib/mittsu/math/vector3.rb +61 -351
  25. data/lib/mittsu/math/vector4.rb +45 -295
  26. data/lib/mittsu/objects/line.rb +12 -2
  27. data/lib/mittsu/objects/mesh.rb +18 -9
  28. data/lib/mittsu/renderers/glfw_window.rb +15 -13
  29. data/lib/mittsu/renderers/opengl/core/opengl_geometry.rb +253 -0
  30. data/lib/mittsu/renderers/opengl/core/opengl_object_3d.rb +131 -0
  31. data/lib/mittsu/renderers/opengl/lights/opengl_ambient_light.rb +26 -0
  32. data/lib/mittsu/renderers/opengl/lights/opengl_directional_light.rb +35 -0
  33. data/lib/mittsu/renderers/opengl/lights/opengl_hemisphere_light.rb +42 -0
  34. data/lib/mittsu/renderers/opengl/lights/opengl_light.rb +52 -0
  35. data/lib/mittsu/renderers/opengl/lights/opengl_point_light.rb +36 -0
  36. data/lib/mittsu/renderers/opengl/lights/opengl_spot_light.rb +47 -0
  37. data/lib/mittsu/renderers/opengl/materials/opengl_line_basic_material.rb +16 -0
  38. data/lib/mittsu/renderers/opengl/materials/opengl_material.rb +275 -0
  39. data/lib/mittsu/renderers/opengl/materials/opengl_mesh_basic_material.rb +69 -0
  40. data/lib/mittsu/renderers/opengl/materials/opengl_mesh_lambert_material.rb +29 -0
  41. data/lib/mittsu/renderers/opengl/materials/opengl_mesh_phong_material.rb +40 -0
  42. data/lib/mittsu/renderers/opengl/materials/opengl_shader_material.rb +11 -0
  43. data/lib/mittsu/renderers/opengl/objects/opengl_group.rb +8 -0
  44. data/lib/mittsu/renderers/opengl/objects/opengl_line.rb +54 -0
  45. data/lib/mittsu/renderers/opengl/objects/opengl_mesh.rb +77 -0
  46. data/lib/mittsu/renderers/opengl/opengl_buffer.rb +5 -0
  47. data/lib/mittsu/renderers/opengl/opengl_debug.rb +49 -7
  48. data/lib/mittsu/renderers/opengl/opengl_default_target.rb +54 -0
  49. data/lib/mittsu/renderers/opengl/opengl_geometry_group.rb +763 -0
  50. data/lib/mittsu/renderers/opengl/opengl_geometry_like.rb +130 -0
  51. data/lib/mittsu/renderers/opengl/opengl_helper.rb +161 -0
  52. data/lib/mittsu/renderers/opengl/opengl_implementations.rb +61 -0
  53. data/lib/mittsu/renderers/opengl/opengl_light_renderer.rb +43 -0
  54. data/lib/mittsu/renderers/opengl/opengl_mittsu_params.rb +53 -0
  55. data/lib/mittsu/renderers/opengl/opengl_program.rb +147 -296
  56. data/lib/mittsu/renderers/opengl/opengl_state.rb +3 -5
  57. data/lib/mittsu/renderers/opengl/plugins/shadow_map_plugin.rb +12 -10
  58. data/lib/mittsu/renderers/opengl/scenes/opengl_scene.rb +8 -0
  59. data/lib/mittsu/renderers/opengl/textures/opengl_compressed_texture.rb +21 -0
  60. data/lib/mittsu/renderers/opengl/textures/opengl_cube_texture.rb +75 -0
  61. data/lib/mittsu/renderers/opengl/textures/opengl_data_texture.rb +23 -0
  62. data/lib/mittsu/renderers/opengl/textures/opengl_texture.rb +111 -0
  63. data/lib/mittsu/renderers/opengl_render_target.rb +117 -2
  64. data/lib/mittsu/renderers/opengl_renderer.rb +653 -2978
  65. data/lib/mittsu/renderers/shaders/rbsl_loader.rb +166 -0
  66. data/lib/mittsu/renderers/shaders/shader_chunk.rb +6 -9
  67. data/lib/mittsu/renderers/shaders/shader_chunk/shadowmap_fragment.glsl +36 -37
  68. data/lib/mittsu/renderers/shaders/shader_lib.rb +26 -403
  69. data/lib/mittsu/renderers/shaders/shader_lib/basic/basic_fragment.rbsl +37 -0
  70. data/lib/mittsu/renderers/shaders/shader_lib/basic/basic_uniforms.rbslu +3 -0
  71. data/lib/mittsu/renderers/shaders/shader_lib/basic/basic_vertex.rbsl +33 -0
  72. data/lib/mittsu/renderers/shaders/shader_lib/cube/cube_fragment.rbsl +12 -0
  73. data/lib/mittsu/renderers/shaders/shader_lib/cube/cube_uniforms.rbslu +2 -0
  74. data/lib/mittsu/renderers/shaders/shader_lib/cube/cube_vertex.rbsl +12 -0
  75. data/lib/mittsu/renderers/shaders/shader_lib/depth_rgba/depth_rgba_fragment.rbsl +26 -0
  76. data/lib/mittsu/renderers/shaders/shader_lib/depth_rgba/depth_rgba_uniforms.rbslu +0 -0
  77. data/lib/mittsu/renderers/shaders/shader_lib/depth_rgba/depth_rgba_vertex.rbsl +12 -0
  78. data/lib/mittsu/renderers/shaders/shader_lib/lambert/lambert_fragment.rbsl +56 -0
  79. data/lib/mittsu/renderers/shaders/shader_lib/lambert/lambert_uniforms.rbslu +7 -0
  80. data/lib/mittsu/renderers/shaders/shader_lib/lambert/lambert_vertex.rbsl +37 -0
  81. data/lib/mittsu/renderers/shaders/shader_lib/phong/phong_fragment.rbsl +45 -0
  82. data/lib/mittsu/renderers/shaders/shader_lib/phong/phong_uniforms.rbslu +11 -0
  83. data/lib/mittsu/renderers/shaders/shader_lib/phong/phong_vertex.rbsl +43 -0
  84. data/lib/mittsu/renderers/shaders/shader_templates/fragment.glsl.erb +105 -0
  85. data/lib/mittsu/renderers/shaders/shader_templates/vertex.glsl.erb +143 -0
  86. data/lib/mittsu/renderers/shaders/uniforms_lib.rb +54 -55
  87. data/lib/mittsu/textures/texture.rb +5 -2
  88. data/lib/mittsu/version.rb +1 -1
  89. data/run_all_examples.sh +7 -0
  90. metadata +77 -28
  91. data/.ruby-version +0 -1
  92. data/lib/mittsu/core/hash_object.rb +0 -19
@@ -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