mittsu-opengl 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (145) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +18 -0
  3. data/.github/workflows/build-workflow.yml +67 -0
  4. data/.gitignore +12 -0
  5. data/.rubocop.yml +1158 -0
  6. data/CODE_OF_CONDUCT.md +13 -0
  7. data/Gemfile +9 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +195 -0
  10. data/Rakefile +8 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +7 -0
  13. data/install-glfw.ps1 +13 -0
  14. data/lib/mittsu/generic_lib.rb +116 -0
  15. data/lib/mittsu/glfw/lib.rb +58 -0
  16. data/lib/mittsu/glfw/window.rb +231 -0
  17. data/lib/mittsu/opengl/buffer.rb +13 -0
  18. data/lib/mittsu/opengl/default_target.rb +50 -0
  19. data/lib/mittsu/opengl/geometry_group.rb +758 -0
  20. data/lib/mittsu/opengl/geometry_like.rb +132 -0
  21. data/lib/mittsu/opengl/gl_debug.rb +85 -0
  22. data/lib/mittsu/opengl/gl_extensions.rb +42 -0
  23. data/lib/mittsu/opengl/gl_mittsu_params.rb +53 -0
  24. data/lib/mittsu/opengl/helper.rb +120 -0
  25. data/lib/mittsu/opengl/implementation.rb +31 -0
  26. data/lib/mittsu/opengl/lib.rb +19 -0
  27. data/lib/mittsu/opengl/light_renderer.rb +43 -0
  28. data/lib/mittsu/opengl/material_basics.rb +57 -0
  29. data/lib/mittsu/opengl/plugins/shadow_map_plugin.rb +416 -0
  30. data/lib/mittsu/opengl/plugins/sprite_fragment.glsl +38 -0
  31. data/lib/mittsu/opengl/plugins/sprite_plugin.rb +250 -0
  32. data/lib/mittsu/opengl/plugins/sprite_vertex.glsl +31 -0
  33. data/lib/mittsu/opengl/program.rb +250 -0
  34. data/lib/mittsu/opengl/renderer.rb +1028 -0
  35. data/lib/mittsu/opengl/shader/chunk.rb +11 -0
  36. data/lib/mittsu/opengl/shader/chunks/alphamap_fragment.glsl +5 -0
  37. data/lib/mittsu/opengl/shader/chunks/alphamap_pars_fragment.glsl +5 -0
  38. data/lib/mittsu/opengl/shader/chunks/alphatest_fragment.glsl +5 -0
  39. data/lib/mittsu/opengl/shader/chunks/bumpmap_pars_fragment.glsl +40 -0
  40. data/lib/mittsu/opengl/shader/chunks/color_fragment.glsl +5 -0
  41. data/lib/mittsu/opengl/shader/chunks/color_pars_fragment.glsl +5 -0
  42. data/lib/mittsu/opengl/shader/chunks/color_pars_vertex.glsl +5 -0
  43. data/lib/mittsu/opengl/shader/chunks/color_vertex.glsl +5 -0
  44. data/lib/mittsu/opengl/shader/chunks/common.glsl +60 -0
  45. data/lib/mittsu/opengl/shader/chunks/default_vertex.glsl +15 -0
  46. data/lib/mittsu/opengl/shader/chunks/defaultnormal_vertex.glsl +21 -0
  47. data/lib/mittsu/opengl/shader/chunks/envmap_fragment.glsl +62 -0
  48. data/lib/mittsu/opengl/shader/chunks/envmap_pars_fragment.glsl +21 -0
  49. data/lib/mittsu/opengl/shader/chunks/envmap_pars_vertex.glsl +7 -0
  50. data/lib/mittsu/opengl/shader/chunks/envmap_vertex.glsl +17 -0
  51. data/lib/mittsu/opengl/shader/chunks/fog_fragment.glsl +26 -0
  52. data/lib/mittsu/opengl/shader/chunks/fog_pars_fragment.glsl +15 -0
  53. data/lib/mittsu/opengl/shader/chunks/lightmap_fragment.glsl +5 -0
  54. data/lib/mittsu/opengl/shader/chunks/lightmap_pars_fragment.glsl +6 -0
  55. data/lib/mittsu/opengl/shader/chunks/lightmap_pars_vertex.glsl +5 -0
  56. data/lib/mittsu/opengl/shader/chunks/lightmap_vertex.glsl +5 -0
  57. data/lib/mittsu/opengl/shader/chunks/lights_lambert_pars_vertex.glsl +43 -0
  58. data/lib/mittsu/opengl/shader/chunks/lights_lambert_vertex.glsl +196 -0
  59. data/lib/mittsu/opengl/shader/chunks/lights_phong_fragment.glsl +243 -0
  60. data/lib/mittsu/opengl/shader/chunks/lights_phong_pars_fragment.glsl +58 -0
  61. data/lib/mittsu/opengl/shader/chunks/lights_phong_pars_vertex.glsl +5 -0
  62. data/lib/mittsu/opengl/shader/chunks/lights_phong_vertex.glsl +5 -0
  63. data/lib/mittsu/opengl/shader/chunks/linear_to_gamma_fragment.glsl +2 -0
  64. data/lib/mittsu/opengl/shader/chunks/logdepthbuf_fragment.glsl +5 -0
  65. data/lib/mittsu/opengl/shader/chunks/logdepthbuf_pars_fragment.glsl +12 -0
  66. data/lib/mittsu/opengl/shader/chunks/logdepthbuf_pars_vertex.glsl +11 -0
  67. data/lib/mittsu/opengl/shader/chunks/logdepthbuf_vertex.glsl +15 -0
  68. data/lib/mittsu/opengl/shader/chunks/map_fragment.glsl +9 -0
  69. data/lib/mittsu/opengl/shader/chunks/map_pars_fragment.glsl +11 -0
  70. data/lib/mittsu/opengl/shader/chunks/map_pars_vertex.glsl +6 -0
  71. data/lib/mittsu/opengl/shader/chunks/map_particle_fragment.glsl +5 -0
  72. data/lib/mittsu/opengl/shader/chunks/map_particle_pars_fragment.glsl +6 -0
  73. data/lib/mittsu/opengl/shader/chunks/map_vertex.glsl +5 -0
  74. data/lib/mittsu/opengl/shader/chunks/morphnormal_vertex.glsl +12 -0
  75. data/lib/mittsu/opengl/shader/chunks/morphtarget_pars_vertex.glsl +13 -0
  76. data/lib/mittsu/opengl/shader/chunks/morphtarget_vertex.glsl +20 -0
  77. data/lib/mittsu/opengl/shader/chunks/normalmap_pars_fragment.glsl +27 -0
  78. data/lib/mittsu/opengl/shader/chunks/shadowmap_fragment.glsl +216 -0
  79. data/lib/mittsu/opengl/shader/chunks/shadowmap_pars_fragment.glsl +19 -0
  80. data/lib/mittsu/opengl/shader/chunks/shadowmap_pars_vertex.glsl +6 -0
  81. data/lib/mittsu/opengl/shader/chunks/shadowmap_vertex.glsl +9 -0
  82. data/lib/mittsu/opengl/shader/chunks/skinbase_vertex.glsl +8 -0
  83. data/lib/mittsu/opengl/shader/chunks/skinning_pars_vertex.glsl +47 -0
  84. data/lib/mittsu/opengl/shader/chunks/skinning_vertex.glsl +20 -0
  85. data/lib/mittsu/opengl/shader/chunks/skinnormal_vertex.glsl +20 -0
  86. data/lib/mittsu/opengl/shader/chunks/specularmap_fragment.glsl +12 -0
  87. data/lib/mittsu/opengl/shader/chunks/specularmap_pars_fragment.glsl +5 -0
  88. data/lib/mittsu/opengl/shader/chunks/worldpos_vertex.glsl +17 -0
  89. data/lib/mittsu/opengl/shader/lib/basic/basic_fragment.rbsl +37 -0
  90. data/lib/mittsu/opengl/shader/lib/basic/basic_uniforms.rbslu +3 -0
  91. data/lib/mittsu/opengl/shader/lib/basic/basic_vertex.rbsl +33 -0
  92. data/lib/mittsu/opengl/shader/lib/cube/cube_fragment.rbsl +12 -0
  93. data/lib/mittsu/opengl/shader/lib/cube/cube_uniforms.rbslu +2 -0
  94. data/lib/mittsu/opengl/shader/lib/cube/cube_vertex.rbsl +12 -0
  95. data/lib/mittsu/opengl/shader/lib/depth_rgba/depth_rgba_fragment.rbsl +26 -0
  96. data/lib/mittsu/opengl/shader/lib/depth_rgba/depth_rgba_uniforms.rbslu +0 -0
  97. data/lib/mittsu/opengl/shader/lib/depth_rgba/depth_rgba_vertex.rbsl +12 -0
  98. data/lib/mittsu/opengl/shader/lib/lambert/lambert_fragment.rbsl +56 -0
  99. data/lib/mittsu/opengl/shader/lib/lambert/lambert_uniforms.rbslu +7 -0
  100. data/lib/mittsu/opengl/shader/lib/lambert/lambert_vertex.rbsl +37 -0
  101. data/lib/mittsu/opengl/shader/lib/particle_basic/particle_basic_fragment.rbsl +27 -0
  102. data/lib/mittsu/opengl/shader/lib/particle_basic/particle_basic_uniforms.rbslu +2 -0
  103. data/lib/mittsu/opengl/shader/lib/particle_basic/particle_basic_vertex.rbsl +25 -0
  104. data/lib/mittsu/opengl/shader/lib/phong/phong_fragment.rbsl +45 -0
  105. data/lib/mittsu/opengl/shader/lib/phong/phong_uniforms.rbslu +11 -0
  106. data/lib/mittsu/opengl/shader/lib/phong/phong_vertex.rbsl +43 -0
  107. data/lib/mittsu/opengl/shader/lib.rb +45 -0
  108. data/lib/mittsu/opengl/shader/rbsl_loader.rb +168 -0
  109. data/lib/mittsu/opengl/shader/templates/fragment.glsl.erb +105 -0
  110. data/lib/mittsu/opengl/shader/templates/vertex.glsl.erb +143 -0
  111. data/lib/mittsu/opengl/shader/uniforms_lib.rb +86 -0
  112. data/lib/mittsu/opengl/shader/uniforms_utils.rb +31 -0
  113. data/lib/mittsu/opengl/shader.rb +56 -0
  114. data/lib/mittsu/opengl/state.rb +205 -0
  115. data/lib/mittsu/opengl/version.rb +5 -0
  116. data/lib/mittsu/opengl.rb +2 -0
  117. data/lib/mittsu/opengl_implementation/core/buffer_geometry.rb +11 -0
  118. data/lib/mittsu/opengl_implementation/core/geometry.rb +346 -0
  119. data/lib/mittsu/opengl_implementation/core/object_3d.rb +134 -0
  120. data/lib/mittsu/opengl_implementation/lights/ambient_light.rb +26 -0
  121. data/lib/mittsu/opengl_implementation/lights/directional_light.rb +35 -0
  122. data/lib/mittsu/opengl_implementation/lights/hemisphere_light.rb +39 -0
  123. data/lib/mittsu/opengl_implementation/lights/light.rb +55 -0
  124. data/lib/mittsu/opengl_implementation/lights/point_light.rb +36 -0
  125. data/lib/mittsu/opengl_implementation/lights/spot_light.rb +47 -0
  126. data/lib/mittsu/opengl_implementation/materials/line_basic_material.rb +16 -0
  127. data/lib/mittsu/opengl_implementation/materials/material.rb +274 -0
  128. data/lib/mittsu/opengl_implementation/materials/mesh_basic_material.rb +21 -0
  129. data/lib/mittsu/opengl_implementation/materials/mesh_lambert_material.rb +33 -0
  130. data/lib/mittsu/opengl_implementation/materials/mesh_phong_material.rb +44 -0
  131. data/lib/mittsu/opengl_implementation/materials/point_cloud_material.rb +27 -0
  132. data/lib/mittsu/opengl_implementation/materials/shader_material.rb +11 -0
  133. data/lib/mittsu/opengl_implementation/objects/group.rb +9 -0
  134. data/lib/mittsu/opengl_implementation/objects/line.rb +45 -0
  135. data/lib/mittsu/opengl_implementation/objects/mesh.rb +70 -0
  136. data/lib/mittsu/opengl_implementation/objects/point_cloud.rb +39 -0
  137. data/lib/mittsu/opengl_implementation/objects/sprite.rb +12 -0
  138. data/lib/mittsu/opengl_implementation/scenes/scene.rb +9 -0
  139. data/lib/mittsu/opengl_implementation/textures/compressed_texture.rb +20 -0
  140. data/lib/mittsu/opengl_implementation/textures/cube_texture.rb +77 -0
  141. data/lib/mittsu/opengl_implementation/textures/data_texture.rb +21 -0
  142. data/lib/mittsu/opengl_implementation/textures/render_target.rb +124 -0
  143. data/lib/mittsu/opengl_implementation/textures/texture.rb +107 -0
  144. data/mittsu-opengl.gemspec +36 -0
  145. metadata +314 -0
@@ -0,0 +1,1028 @@
1
+ require 'opengl'
2
+ require 'glfw'
3
+ require 'fiddle'
4
+
5
+ require 'mittsu/opengl/version'
6
+ require 'mittsu/opengl/lib'
7
+ opengl_lib = Mittsu::OpenGL::Lib.discover
8
+ GL.load_lib(ENV["MITTSU_LIBGL_PATH"] || opengl_lib.path, Mittsu.debug?)
9
+
10
+ require 'mittsu/glfw/window'
11
+ require 'mittsu/opengl/gl_debug' if ENV['DEBUG']
12
+ require 'mittsu/opengl/implementation'
13
+ require 'mittsu/opengl/gl_extensions'
14
+ require 'mittsu/opengl/helper'
15
+ require 'mittsu/opengl/program'
16
+ require 'mittsu/opengl/state'
17
+ require 'mittsu/opengl/geometry_group'
18
+ require 'mittsu/opengl/light_renderer'
19
+ require 'mittsu/opengl/default_target'
20
+ require 'mittsu/opengl/buffer'
21
+ require 'mittsu/opengl/plugins/shadow_map_plugin'
22
+ require 'mittsu/opengl/plugins/sprite_plugin'
23
+ require 'mittsu/opengl/shader/lib'
24
+ require 'mittsu/opengl/shader/uniforms_utils'
25
+ include Mittsu::OpenGL::Helper
26
+
27
+ require 'mittsu/opengl/gl_mittsu_params'
28
+
29
+ module Mittsu
30
+ class OpenGL::Renderer
31
+ attr_accessor :auto_clear, :auto_clear_color, :auto_clear_depth, :auto_clear_stencil, :sort_objects, :gamma_factor, :gamma_input,
32
+ :gamma_output, :shadow_map_enabled, :shadow_map_type, :shadow_map_cull_face, :shadow_map_debug, :shadow_map_cascade,
33
+ :max_morph_targets, :max_morph_normals, :info, :pixel_ratio, :window, :width, :height, :state
34
+
35
+ attr_reader :logarithmic_depth_buffer, :programs, :light_renderer, :proj_screen_matrix
36
+
37
+ def initialize(parameters = {})
38
+ puts "Mittsu OpenGL Renderer #{VERSION}"
39
+
40
+ fetch_parameters(parameters)
41
+
42
+ @pixel_ratio = 1.0
43
+ @sort_objects = true
44
+
45
+ init_collections
46
+ init_clearing
47
+ init_gamma
48
+ init_shadow_properties
49
+ init_morphs
50
+ init_info
51
+ init_state_cache
52
+ init_camera_matrix_cache
53
+
54
+ @light_renderer = OpenGL::LightRenderer.new(self)
55
+
56
+ create_window
57
+
58
+ @state = OpenGL::State.new
59
+
60
+ # TODO: load extensions??
61
+
62
+ reset_gl_state
63
+ set_default_gl_state
64
+
65
+ get_gpu_capabilities
66
+
67
+ init_plugins
68
+ end
69
+
70
+ def supports_bone_textures?
71
+ @_supports_bone_textures
72
+ end
73
+
74
+ def supports_vertex_textures?
75
+ @_supports_vertex_textures
76
+ end
77
+
78
+ def shadow_map_enabled?
79
+ @shadow_map_enabled
80
+ end
81
+
82
+ # TODO: get_context ???
83
+ # TODO: force_context_loss ???
84
+ # TODO: supports_float_textures? ???
85
+ # TODO: supports[half|standard|compressed|blend min max] ... ???
86
+
87
+ def max_anisotropy
88
+ @_max_anisotropy ||= nil
89
+ # TODO: get max anisotropy ????
90
+ end
91
+
92
+ def set_size(width, height)
93
+ @width, @height = width, height
94
+ self.set_viewport(0, 0, width, height)
95
+ end
96
+
97
+ def set_viewport(x, y, width, height)
98
+ default_target.set_and_use_viewport(
99
+ x * pixel_ratio,
100
+ y * pixel_ratio,
101
+ width * pixel_ratio,
102
+ height * pixel_ratio
103
+ )
104
+ end
105
+
106
+ def set_scissor(x, y, width, height)
107
+ GL.Scissor(
108
+ x * pixel_ratio,
109
+ y * pixel_ratio,
110
+ width * pixel_ratio,
111
+ height * pixel_ratio
112
+ )
113
+ end
114
+
115
+ def enable_scissor_test(enable)
116
+ enable ? GL.Enable(GL::SCISSOR_TEST) : GL.Disable(GL::SCISSOR_TEST)
117
+ end
118
+
119
+ def object_in_frustum?(object)
120
+ @_frustum.intersects_object?(object)
121
+ end
122
+
123
+ def sort_objects?
124
+ @sort_objects
125
+ end
126
+
127
+ # clearing
128
+
129
+ def get_clear_color
130
+ @_clear_color
131
+ end
132
+
133
+ def set_clear_color(color, alpha = 1.0)
134
+ @_clear_color.set(color)
135
+ @_clear_alpha = alpha
136
+ clear_color(@_clear_color.r, @_clear_color.g, @_clear_color.b, @_clear_alpha)
137
+ end
138
+
139
+ def get_clear_alpha
140
+ @_clear_alpha
141
+ end
142
+
143
+ def set_clear_alpha(alpha)
144
+ @_clear_alpha = alpha
145
+ clear_color(@_clear_color.r, @_clear_color.g, @_clear_color.b, @_clear_alpha)
146
+ end
147
+
148
+ def clear(color = true, depth = true, stencil = true)
149
+ bits = 0
150
+
151
+ bits |= GL::COLOR_BUFFER_BIT if color
152
+ bits |= GL::DEPTH_BUFFER_BIT if depth
153
+ bits |= GL::STENCIL_BUFFER_BIT if stencil
154
+
155
+ GL.Clear(bits)
156
+ end
157
+
158
+ def clear_depth
159
+ GL.Clear(GL::DEPTH_BUFFER_BIT)
160
+ end
161
+
162
+ def clear_stencil
163
+ GL.Clear(GL::STENCIL_BUFFER_BIT)
164
+ end
165
+
166
+ def clear_target(render_target, color, depth, stencil)
167
+ set_render_target(render_target)
168
+ clear(color, depth, stencil)
169
+ end
170
+
171
+ def reset_gl_state
172
+ @_current_program = nil
173
+ @_current_camera = nil
174
+
175
+ @_current_geometry_program = ''
176
+ @_current_material_id = -1
177
+
178
+ @light_renderer.reset
179
+
180
+ @state.reset
181
+ end
182
+
183
+ def set_render_target(render_target = default_target)
184
+ # TODO: when OpenGLRenderTargetCube exists
185
+ # is_cube = render_target.is_a? OpenGLRenderTargetCube
186
+
187
+ # TODO framebuffer logic for render target cube
188
+ render_target.setup_buffers
189
+
190
+ if render_target != @_current_render_target
191
+ render_target.use
192
+ @_current_render_target = render_target
193
+ end
194
+ end
195
+
196
+ def render(scene, camera, render_target = default_target, force_clear = false)
197
+ raise "ERROR: Mittsu::OpenGL::Renderer#render: camera is not an instance of Mittsu::Camera" unless camera.is_a?(Camera)
198
+
199
+ reset_cache_for_this_frame
200
+
201
+ scene.update_matrix_world if scene.auto_update
202
+ camera.update_matrix_world if camera.parent.nil?
203
+
204
+ update_skeleton_objects(scene)
205
+
206
+ update_screen_projection(camera)
207
+ scene.project(self)
208
+ sort_objects_for_render if @sort_objects
209
+
210
+ render_custom_plugins_pre_pass(scene, camera)
211
+
212
+ set_matrices_for_immediate_objects(camera)
213
+
214
+ set_render_target(render_target)
215
+ perform_auto_clear if @auto_clear || force_clear
216
+ render_main_pass(scene, camera)
217
+
218
+ render_custom_plugins_post_pass(scene, camera)
219
+
220
+ render_target.update_mipmap
221
+
222
+ ensure_depth_buffer_writing
223
+ end
224
+
225
+ def set_material_faces(material)
226
+ @state.set_double_sided(material.side == DoubleSide)
227
+ @state.set_flip_sided(material.side == BackSide)
228
+ end
229
+
230
+ def render_buffer(camera, lights, fog, material, geometry_group, object)
231
+ puts "--- RENDER #{object.name}" if DEBUG
232
+ return unless material.visible
233
+
234
+ geometry_group.renderer = self
235
+ geometry_group.bind_vertex_array_object
236
+
237
+ update_object(object)
238
+
239
+ program = set_program(camera, lights, fog, material, object)
240
+ attributes = program.attributes
241
+ buffers_need_update = switch_geometry_program(program, material, geometry_group)
242
+
243
+ @state.init_attributes if buffers_need_update
244
+
245
+ if !material.morph_targets && attributes['position'] && attributes['position'] >= 0
246
+ geometry_group.update_vertex_buffer(attributes['position']) if buffers_need_update
247
+ elsif object.morph_target_base
248
+ # TODO: when morphing is implemented
249
+ # setup_morph_targets(material, geometry_group, object)
250
+ end
251
+
252
+ if buffers_need_update
253
+ geometry_group.update_other_buffers(object, material, attributes)
254
+ end
255
+
256
+ @state.disable_unused_attributes
257
+
258
+ object.render_buffer(camera, lights, fog, material, geometry_group, buffers_need_update)
259
+ end
260
+
261
+ def compressed_texture_formats
262
+ # TODO: needs extensions.get ...
263
+
264
+ @_compressed_texture_formats ||= []
265
+ end
266
+
267
+ # Events
268
+
269
+ def on_object_removed(event)
270
+ object = event.target
271
+ object.traverse do |child|
272
+ child.remove_event_listener(:remove, method(:on_object_removed))
273
+ remove_child(child)
274
+ end
275
+ end
276
+
277
+ def on_geometry_dispose(event)
278
+ geometry = event.target
279
+ geometry.remove_event_listener(:dispose, method(:on_geometry_dispose))
280
+ deallocate_geometry(geometry)
281
+ end
282
+
283
+ def on_texture_dispose(event)
284
+ texture = event.target
285
+ texture.remove_event_listener(:dispose, method(:on_texture_dispose))
286
+ deallocate_texture(texture)
287
+ @info[:memory][:textures] -= 1
288
+ end
289
+
290
+ def on_render_target_dispose(event)
291
+ render_target = event.target
292
+ render_target.remove_event_listener(:dispose, method(:on_render_target_dispose))
293
+ deallocate_render_target(render_target)
294
+ @info[:memory][:textures] -= 1
295
+ end
296
+
297
+ def on_material_dispose(event)
298
+ material = event.target
299
+ material.remove_event_listener(:dispose, method(:on_material_dispose))
300
+ deallocate_material(material)
301
+ end
302
+
303
+ def clamp_to_max_size(image, max_size = @_max_texture_size)
304
+ width, height = image.width, image.height
305
+ if width > max_size || height > max_size
306
+ # TODO: scale the image ...
307
+
308
+ puts "WARNING: Mittsu::OpenGL::Renderer: image is too big (#{width} x #{height}). Resized to #{@_max_texture_size} x #{@_max_texture_size}"
309
+ end
310
+ image
311
+ end
312
+
313
+ def add_opengl_object(buffer, object)
314
+ add_buffer(@_opengl_objects, buffer, object)
315
+ end
316
+
317
+ def remove_opengl_object(object)
318
+ @_opengl_objects.delete(object.id)
319
+ end
320
+
321
+ private
322
+
323
+ def clear_color(r, g, b, a)
324
+ if (@_premultiplied_alpha)
325
+ r *= a; g *= a; b *= a
326
+ end
327
+
328
+ GL.ClearColor(r, g, b, a)
329
+ end
330
+
331
+ def set_default_gl_state
332
+ GL.ClearColor(0.0, 0.0, 0.0, 1.0)
333
+ GL.ClearDepth(1)
334
+ GL.ClearStencil(0)
335
+
336
+ GL.Enable(GL::DEPTH_TEST)
337
+ GL.DepthFunc(GL::LEQUAL)
338
+
339
+ GL.FrontFace(GL::CCW)
340
+ GL.CullFace(GL::BACK)
341
+ GL.Enable(GL::CULL_FACE)
342
+
343
+ GL.Enable(GL::BLEND)
344
+ GL.BlendEquation(GL::FUNC_ADD)
345
+ GL.BlendFunc(GL::SRC_ALPHA, GL::ONE_MINUS_SRC_ALPHA)
346
+
347
+ default_target.use_viewport
348
+
349
+ clear_color(@_clear_color.r, @_clear_color.g, @_clear_color.b, @_clear_alpha)
350
+ end
351
+
352
+ def render_objects(render_list, camera, lights, fog, override_material)
353
+ material = nil
354
+ render_list.each do |opengl_object|
355
+ puts "-- RENDER_OBJECT #{opengl_object.name}" if DEBUG
356
+ object = opengl_object.object
357
+ buffer = opengl_object.buffer
358
+
359
+ object.setup_matrices(camera)
360
+
361
+ if override_material
362
+ material = override_material
363
+ else
364
+ material = opengl_object.material
365
+ next unless material
366
+ material.set(self)
367
+ end
368
+
369
+ set_material_faces(material)
370
+ if buffer.is_a? BufferGeometry
371
+ # TODO
372
+ # render_buffer_direct(camera, lights, fog, material, buffer, object)
373
+ else
374
+ puts "-- RENDER COLOR #{material.color}" if DEBUG
375
+ render_buffer(camera, lights, fog, material, buffer, object)
376
+ end
377
+ end
378
+ end
379
+
380
+ def render_objects_immediate(render_list, material_type, camera, lights, fog, override_material)
381
+ material = nil
382
+ render_list.each do |opengl_object|
383
+ object = opengl_object.object
384
+ if object.visible
385
+ if override_material
386
+ material = override_material
387
+ else
388
+ material = case material_type
389
+ when :transparent then opengl_object.transparent
390
+ when :opaque then opengl_object.opaque
391
+ else nil
392
+ end
393
+ next unless material
394
+ material.set(self)
395
+ end
396
+ render_immediate_object(camera, lights, fog, material, object)
397
+ end
398
+ end
399
+ end
400
+
401
+ def add_buffer(objlist, buffer, object)
402
+ id = object.id
403
+ (objlist[id] ||= []) << OpenGL::Buffer.new(
404
+ buffer, object, nil, 0
405
+ )
406
+ end
407
+
408
+ def unroll_immediate_buffer_material(opengl_object)
409
+ object = opengl_object.object
410
+ material = object.material
411
+
412
+ if material.transparent
413
+ opengl_object.transparent
414
+ opengl_object.opaque = nil
415
+ else
416
+ opengl_object.opaque = material
417
+ opengl_object.transparent = nil
418
+ end
419
+ end
420
+
421
+ def unroll_buffer_material(opengl_object)
422
+ object = opengl_object.object
423
+ buffer = opengl_object.buffer
424
+
425
+ geometry = object.geometry
426
+ material = object.material
427
+
428
+ if material
429
+ puts "--- UNROLL #{opengl_object.name}" if DEBUG
430
+ if material.is_a? MeshFaceMaterial
431
+ material_index = geometry.is_a?(BufferGeometry) ? 0 : buffer.material_index
432
+ material = material.materials[material_index]
433
+ end
434
+
435
+ opengl_object.material = material
436
+
437
+ if material.transparent
438
+ @transparent_objects << opengl_object
439
+ else
440
+ @opaque_objects << opengl_object
441
+ end
442
+ end
443
+ end
444
+
445
+ # FIXME: refactor
446
+ def update_object(object)
447
+ geometry = object.geometry
448
+
449
+ if geometry.is_a? BufferGeometry
450
+ # TODO: geometry vertex array ?????
451
+ # GL.BindVertexArray geometry.vertex_array
452
+
453
+ geometry.attributes.each do |(key, attribute)|
454
+ buffer_type = (key == 'index') ? GL::ELEMENT_ARRAY_BUFFER : GL::ARRAY_BUFFER
455
+
456
+ if attribute.buffer.nil?
457
+ attribute.buffer = GL.CreateBuffer
458
+ GL.BindBuffer(buffer_type, attribute.buffer)
459
+ GL.BufferData_easy(buffer_type, attribute.array, (attribute.is_a? DynamicBufferAttribute) ? GL::DYNAMIC_DRAW : GL::STATIC_DRAW)
460
+
461
+ attribute.needs_update = false
462
+ elsif attribute.needs_update
463
+ GL.BindBuffer(buffer_type, attribute.buffer)
464
+ if attribute.update_range.nil? || attribute.update_range.count == -1 # Not using update ranged
465
+ GL.BufferSubData(buffer_type, 0, attribute.array)
466
+ elsif attribute.udpate_range.count.zero?
467
+ puts 'ERROR: Mittsu::OpenGL::Renderer#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.'
468
+ else
469
+ # TODO: make a GL.BufferSubData_easy method
470
+ GL.BufferSubData(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))
471
+ attribute.update_range.count = 0 # reset range
472
+ end
473
+
474
+ attribute.needs_update = false
475
+ end
476
+ end
477
+ else
478
+ object.update
479
+ end
480
+ end
481
+
482
+ # FIXME: refactor
483
+ def set_program(camera, lights, fog, material, object)
484
+ @_used_texture_units = 0
485
+ if material.needs_update?
486
+ deallocate_material(material) if material.program
487
+
488
+ material.init(lights, fog, object, self)
489
+ material.needs_update = false
490
+ end
491
+
492
+ if material.morph_targets
493
+ if !object.morph_target_influences
494
+ object.morph_target_influences = Array.new(@max_morph_targets) # Float32Array
495
+ end
496
+ end
497
+
498
+ refresh_program = false
499
+ refresh_material = false
500
+ refresh_lights = false
501
+
502
+ program = material.program
503
+ program_uniforms = program.uniforms
504
+ material_uniforms = material.shader[:uniforms]
505
+
506
+ if program.id != @_current_program
507
+ GL.UseProgram(program.program)
508
+ @_current_program = program.id
509
+
510
+ refresh_program = true
511
+ refresh_material = true
512
+ refresh_lights = true
513
+ end
514
+
515
+ if material.id != @_current_material_id
516
+ refresh_lights = true if @_current_material_id == -1
517
+ @_current_material_id = material.id
518
+
519
+ refresh_material = true
520
+ end
521
+
522
+ if refresh_program || camera != @_current_camera
523
+ @_current_camera = camera
524
+ update_camera_uniforms(program_uniforms, camera, material)
525
+ end
526
+
527
+ if material.skinning
528
+ # TODO: when skinning is implemented. Then also refactor
529
+ # if object.bind_matrix && !program_uniforms['bindMatrix'].nil?
530
+ # GL.UniformMatrix4fv(program_uniforms['bindMatrix'], GL::FALSE, object.bind_matrix.elements)
531
+ # end
532
+ #
533
+ # if object.bind_matrix_inverse && !program_uniforms['bindMatrixInverse'].nil?
534
+ # GL.UniformMatrix4fv(program_uniforms['bindMatrixInverse'], GL::FALSE, object.bind_matrix_inverse.elements)
535
+ # end
536
+ #
537
+ # if @_supports_bone_textures && object.skeleton && object.skeleton.use_vertex_texture
538
+ # if !program_uniforms['boneTexture'].nil?
539
+ # texture_unit = get_texture_unit
540
+ #
541
+ # GL.Uniform1i(program_uniforms['boneTexture'], texture_unit)
542
+ # object.skeleton.bone_texture.set(texture_unit, self)
543
+ # end
544
+ #
545
+ # if !program_uniforms['boneTextureWidth'].nil?
546
+ # GL.Uniform1i(program_uniforms['boneTextureWidth'], object.skeleton.bone_texture_width)
547
+ # end
548
+ #
549
+ # if !program_uniforms['boneTextureHeight'].nil?
550
+ # GL.Uniform1i(program_uniforms['boneTextureHeight'], object.skeleton.bone_texture_height)
551
+ # end
552
+ # elsif object.skeleton && object.skeleton.bone_matrices
553
+ # if !program_uniforms['boneGlobalMatrices'].nil?
554
+ # GL.UniformMatrix4fv(program_uniforms['boneGlobalMatrices'], GL::FALSE, object.skeleton.bone_matrices)
555
+ # end
556
+ # end
557
+ end
558
+
559
+ if refresh_material
560
+ # TODO: when fog is implemented
561
+ # refresh_uniforms_fog(material_uniforms, fog) if fog && material.fog
562
+
563
+ if material.needs_lights?
564
+ if @light_renderer.lights_need_update
565
+ refresh_lights = true
566
+ @light_renderer.setup(lights)
567
+ end
568
+
569
+ if refresh_lights
570
+ OpenGL::Helper.refresh_uniforms_lights(material_uniforms, @light_renderer.cache)
571
+ end
572
+
573
+ OpenGL::Helper.mark_uniforms_lights_needs_update(material_uniforms, refresh_lights)
574
+ end
575
+
576
+ material.refresh_uniforms(material_uniforms)
577
+
578
+ # TODO: when all of these things exist
579
+ # when LineDashedMaterial
580
+ # refresh_uniforms_line(material_uniforms, material)
581
+ # refresh_uniforms_dash(material_uniforms, material)
582
+ # when MeshDepthMaterial
583
+ # material_uniforms.m_near.value = camera.near
584
+ # material_uniforms.m_far.value = camera.far
585
+ # material_uniforms.opacity.value = material.opacity
586
+ # when MeshNormalMaterial
587
+ # material_uniforms.opactity.value = material.opacity
588
+
589
+ if object.receive_shadow && !material.shadow_pass
590
+ OpenGL::Helper.refresh_uniforms_shadow(material_uniforms, lights)
591
+ end
592
+
593
+ load_uniforms_generic(material.uniforms_list)
594
+ end
595
+
596
+ object.load_uniforms_matrices(program_uniforms)
597
+
598
+ if !program_uniforms['modelMatrix'].nil?
599
+ GL.UniformMatrix4fv(program_uniforms['modelMatrix'], 1, GL::FALSE, array_to_ptr_easy(object.matrix_world.elements))
600
+ end
601
+
602
+ program
603
+ end
604
+
605
+ # FIXME: REFACTOR!?!?!?!?!???
606
+ # MASSIVE CASE STATEMENT OMG!!!
607
+ def load_uniforms_generic(uniforms)
608
+ uniforms.each do |(uniform, location)|
609
+ # needs_update property is not added to all uniforms.
610
+ next if uniform.needs_update == false || location == -1
611
+
612
+ type = uniform.type
613
+ value = uniform.value
614
+
615
+ # AAAAAHHHHH!!!!! \o/ *flips table*
616
+ case type
617
+ when :int
618
+ GL.Uniform1i(location, value)
619
+ when :ivec2
620
+ GL.Uniform2i(location, value[0], value[1])
621
+ when :ivec3
622
+ GL.Uniform3i(location, value[0], value[1], value[2])
623
+ when :ivec4
624
+ GL.Uniform4i(location, value[0], value[1], value[2], value[3])
625
+ when :float
626
+ GL.Uniform1f(location, value)
627
+ when :vec2
628
+ GL.Uniform2f(location, value[0], value[1])
629
+ when :vec3, :color
630
+ GL.Uniform3f(location, value[0], value[1], value[2])
631
+ when :vec4
632
+ GL.Uniform4f(location, value[0], value[1], value[2], value[3])
633
+ when :'int[]'
634
+ GL.Uniform1iv(location, value.length, array_to_ptr_easy(value))
635
+ when :'ivec2[]'
636
+ GL.Uniform2iv(location, value.length / 2, array_to_ptr_easy(value))
637
+ when :'ivec3[]'
638
+ GL.Uniform3iv(location, value.length / 3, array_to_ptr_easy(value))
639
+ when :'ivec4[]'
640
+ GL.Uniform4iv(location, value.length / 4, array_to_ptr_easy(value))
641
+ when :'float[]'
642
+ GL.Uniform1fv(location, value.length, array_to_ptr_easy(value))
643
+ when :'vec2[]'
644
+ if value[0].is_a? Vector2
645
+ uniform.array ||= value.flat_map(&:to_a) # TODO: Float32Array
646
+ GL.Uniform2fv(location, value.length, array_to_ptr_easy(uniform.array))
647
+ else
648
+ GL.Uniform2fv(location, value.length / 2, array_to_ptr_easy(value))
649
+ end
650
+ when :'vec3[]', :'color[]'
651
+ if value.first.is_a?(Vector3) || value.first.is_a?(Color)
652
+ uniform.array ||= value.flat_map(&:to_a) # TODO: Float32Array
653
+ GL.Uniform3fv(location, value.length, array_to_ptr_easy(uniform.array))
654
+ else
655
+ GL.Uniform3fv(location, value.length / 3, array_to_ptr_easy(value))
656
+ end
657
+ when :'vec4[]'
658
+ if value.first.is_a? Vector4
659
+ uniform.array ||= value.flat_map(&:to_a) # TODO: Float32Array
660
+ GL.Uniform4fv(location, value.length, array_to_ptr_easy(uniform.array))
661
+ else
662
+ GL.Uniform4fv(location, value.length / 4, array_to_ptr_easy(value))
663
+ end
664
+ when :mat3
665
+ GL.UniformMatrix3fv(location, 1, GL::FALSE, array_to_ptr_easy(value.to_a))
666
+ when :mat4
667
+ GL.UniformMatrix4fv(location, 1, GL::FALSE, array_to_ptr_easy(value.to_a))
668
+ when :'mat3[]'
669
+ if value.first.is_a? Matrix3
670
+ uniform.array ||= Array.new(9 * value.length) # Float32Array
671
+
672
+ value.each_with_index do |v, i|
673
+ value[i].flatten_to_array_offset(uniform.array, i * 9)
674
+ end
675
+
676
+ GL.UniformMatrix3fv(location, value.length, GL::FALSE, array_to_ptr_easy(uniform.array))
677
+ else
678
+ GL.UniformMatrix3fv(location, value.length / 9, GL::FALSE, array_to_ptr_easy(value))
679
+ end
680
+ when :'mat4[]'
681
+ if value.first.is_a? Matrix4
682
+ uniform.array ||= Array.new(16 * value.length) # Float32Array
683
+
684
+ value.each_with_index do |v, i|
685
+ value[i].flatten_to_array_offset(uniform.array, i * 16)
686
+ end
687
+
688
+ GL.UniformMatrix4fv(location, value.length, GL::FALSE, array_to_ptr_easy(uniform.array))
689
+ else
690
+ GL.UniformMatrix4fv(location, value.length / 16, GL::FALSE, array_to_ptr_easy(value))
691
+ end
692
+ when :texture
693
+ # single Mittsu::Texture (2d or cube)
694
+ texture = value
695
+ texture_unit = get_texture_unit
696
+
697
+ GL.Uniform1i(location, texture_unit)
698
+
699
+ next unless texture
700
+
701
+ texture.set(texture_unit, self)
702
+ # TODO: when OpenGLRenderTargetCube is defined
703
+ # elsif texture.is_a?(OpenGLRenderTargetCube)
704
+ # set_cube_texture_dynamic(texture, texture_unit)
705
+ when :'texture[]'
706
+ # array of Mittsu::Texture (2d)
707
+ uniform.array ||= []
708
+
709
+ uniform.value.each_index do |i|
710
+ uniform.array[i] = get_texture_unit
711
+ end
712
+
713
+ GL.Uniform1iv(location, uniform.array.length, array_to_ptr_easy(uniform.array))
714
+
715
+ uniform.value.each_with_index do |tex, i|
716
+ tex_unit = uniform.array[i]
717
+
718
+ next unless tex
719
+
720
+ tex.set(tex_unit, self)
721
+ end
722
+ else
723
+ puts "WARNING: Mittsu::OpenGL::Renderer: Unknown uniform type: #{type}"
724
+ end
725
+ end
726
+ end
727
+
728
+ def get_texture_unit
729
+ texture_unit = @_used_texture_units
730
+
731
+ if texture_unit >= @_max_textures
732
+ puts "WARNING: OpenGL::Renderer: trying to use #{texture_unit} texture units while this GPU supports only #{@_max_textures}"
733
+ end
734
+
735
+ @_used_texture_units += 1
736
+ texture_unit
737
+ end
738
+
739
+ def ensure_depth_buffer_writing
740
+ @state.set_depth_test(true)
741
+ @state.set_depth_write(true)
742
+ @state.set_color_write(true)
743
+ end
744
+
745
+ def reset_cache
746
+ @_current_geometry_program = ''
747
+ @_current_material_id = -1
748
+ @_current_camera = nil
749
+ @light_renderer.reset
750
+ end
751
+
752
+ def reset_objects_cache
753
+ @lights.clear
754
+ @opaque_objects.clear
755
+ @transparent_objects.clear
756
+ @sprites.clear
757
+ @lens_flares.clear
758
+ end
759
+
760
+ def reset_info
761
+ @info[:render][:calls] = 0
762
+ @info[:render][:vertices] = 0
763
+ @info[:render][:faces] = 0
764
+ @info[:render][:points] = 0
765
+ end
766
+
767
+ def reset_cache_for_this_frame
768
+ reset_cache
769
+ reset_objects_cache
770
+ reset_info
771
+ end
772
+
773
+ def update_screen_projection(camera)
774
+ camera.matrix_world_inverse.inverse(camera.matrix_world)
775
+
776
+ @proj_screen_matrix.multiply_matrices(camera.projection_matrix, camera.matrix_world_inverse)
777
+ @_frustum.set_from_matrix(@proj_screen_matrix)
778
+ end
779
+
780
+ def sort_objects_for_render
781
+ @opaque_objects.sort! { |a,b| OpenGL::Helper.painter_sort_stable(a,b) }
782
+ @transparent_objects.sort! { |a,b| OpenGL::Helper.reverse_painter_sort_stable(a,b) }
783
+ end
784
+
785
+ def set_matrices_for_immediate_objects(camera)
786
+ @_opengl_objects_immediate.each do |opengl_object|
787
+ object = opengl_object.object
788
+
789
+ if object.visible
790
+ object.setup_matrices(camera)
791
+ unroll_immediate_buffer_material(opengl_object)
792
+ end
793
+ end
794
+ end
795
+
796
+ def render_main_pass(scene, camera)
797
+ if scene.override_material
798
+ render_with_override_material(scene, camera)
799
+ else
800
+ render_with_default_materials(scene, camera)
801
+ end
802
+ end
803
+
804
+ def render_with_override_material(scene, camera)
805
+ override_material = scene.override_material
806
+
807
+ override_material.set(self)
808
+
809
+ render_objects(@opaque_objects, camera, @lights, scene.fog, override_material)
810
+ render_objects(@transparent_objects, camera, @lights, scene.fog, override_material)
811
+ render_objects_immediate(@_opengl_objects_immediate, nil, camera, @lights, scene.fog, override_material)
812
+ end
813
+
814
+ def render_with_default_materials(scene, camera)
815
+ render_opaque_pass(scene, camera)
816
+ render_transparent_pass(scene, camera)
817
+ end
818
+
819
+ def render_opaque_pass(scene, camera)
820
+ # front-to-back order
821
+ @state.set_blending(NoBlending)
822
+
823
+ render_objects(@opaque_objects, camera, @lights, scene.fog, nil)
824
+ render_objects_immediate(@_opengl_objects_immediate, :opaque, camera, @lights, scene.fog, nil)
825
+ end
826
+
827
+ def render_transparent_pass(scene, camera)
828
+ # back-to-front-order
829
+ render_objects(@transparent_objects, camera, @lights, scene.fog, nil)
830
+ render_objects_immediate(@_opengl_objects_immediate, :transparent, camera, @lights, scene.fog, nil)
831
+ end
832
+
833
+ def render_custom_plugins_pre_pass(scene, camera)
834
+ @shadow_map_plugin.render(scene, camera)
835
+ end
836
+
837
+ def render_custom_plugins_post_pass(scene, camera)
838
+ @sprite_plugin.render(scene, camera)
839
+
840
+ # TODO: when these custom plugins are implemented
841
+ # lens_flare_plugin.render(scene, camera, @_current_render_target.width, @_current_render_target.height)
842
+ end
843
+
844
+ def update_skeleton_objects(scene)
845
+ # TODO: when SkinnedMesh is defined
846
+ # scene.traverse do |object|
847
+ # if object.is_a? SkinnedMesh
848
+ # object.skeleton.update
849
+ # end
850
+ # end
851
+ end
852
+
853
+ def perform_auto_clear
854
+ clear(@auto_clear_color, @auto_clear_depth, @auto_clear_stencil)
855
+ end
856
+
857
+ def init_clearing
858
+ @_clear_color = Color.new(0x000000)
859
+ @_clear_alpha = 0.0
860
+
861
+ @auto_clear = true
862
+ @auto_clear_color = true
863
+ @auto_clear_depth = true
864
+ @auto_clear_stencil = true
865
+ end
866
+
867
+ def init_gamma
868
+ @gamma_factor = 2.0 # backwards compat???
869
+ @gamma_input = false
870
+ @gamma_output = false
871
+ end
872
+
873
+ def init_shadow_properties
874
+ @shadow_map_enabled = false
875
+ @shadow_map_type = PCFShadowMap
876
+ @shadow_map_cull_face = CullFaceFront
877
+ @shadow_map_debug = false
878
+ @shadow_map_cascade = false
879
+ end
880
+
881
+ def init_morphs
882
+ @max_morph_targets = 8
883
+ @max_morph_normals = 4
884
+ end
885
+
886
+ def init_collections
887
+ @lights = []
888
+ @sprites = []
889
+
890
+ @_opengl_objects = {}
891
+ @_opengl_objects_immediate = []
892
+
893
+ @opaque_objects = []
894
+ @transparent_objects = []
895
+
896
+ @sprites = []
897
+ @lens_flares = []
898
+
899
+ @programs = []
900
+ end
901
+
902
+ def init_info
903
+ @info = {
904
+ memory: {
905
+ programs: 0,
906
+ geometries: 0,
907
+ textures: 0
908
+ },
909
+ render: {
910
+ calls: 0,
911
+ vertices: 0,
912
+ faces: 0,
913
+ points: 0
914
+ }
915
+ }
916
+ end
917
+
918
+ def init_state_cache
919
+ @_current_program = nil
920
+ @_current_render_target = default_target
921
+ @_current_material_id = -1
922
+ @_current_geometry_program = ''
923
+ @_current_camera = nil
924
+
925
+ @_used_texture_units = 0
926
+ end
927
+
928
+ def init_camera_matrix_cache
929
+ @_frustum = Frustum.new
930
+ @proj_screen_matrix = Matrix4.new
931
+ @_vector3 = Vector3.new
932
+ end
933
+
934
+ def fetch_parameters(parameters)
935
+ @_alpha = parameters.fetch(:alpha, false)
936
+ @_depth = parameters.fetch(:depth, true)
937
+ @_stencil = parameters.fetch(:stencil, true)
938
+ @_premultiplied_alpha = parameters.fetch(:premultiplied_alpha, true)
939
+ @_preserve_drawing_buffer = parameters.fetch(:preserve_drawing_buffer, false)
940
+ @logarithmic_depth_buffer = parameters.fetch(:logarithmic_depth_buffer, false)
941
+
942
+ @width = parameters.fetch(:width, 800)
943
+ @height = parameters.fetch(:height, 600)
944
+ @title = parameters.fetch(:title, "Mittsu #{VERSION}")
945
+ @antialias = parameters.fetch(:antialias, 0)
946
+ end
947
+
948
+ def get_gpu_capabilities
949
+ @_max_textures = GL.GetParameter(GL::MAX_TEXTURE_IMAGE_UNITS)
950
+ @_max_vertex_textures = GL.GetParameter(GL::MAX_VERTEX_TEXTURE_IMAGE_UNITS)
951
+ @_max_texture_size = GL.GetParameter(GL::MAX_TEXTURE_SIZE)
952
+ @_max_cubemap_size = GL.GetParameter(GL::MAX_CUBE_MAP_TEXTURE_SIZE)
953
+
954
+ @_supports_vertex_textures = @_max_vertex_textures > 0
955
+ @_supports_bone_textures = @_supports_vertex_textures && false # TODO: extensions.get('OES_texture_float') ????
956
+ end
957
+
958
+ def init_plugins
959
+ @shadow_map_plugin = ShadowMapPlugin.new(self, @lights, @_opengl_objects, @_opengl_objects_immediate)
960
+
961
+ @sprite_plugin = SpritePlugin.new(self, @sprites)
962
+
963
+ # TODO: when these custom plugins are implemented
964
+ # @lens_flare_plugin = LensFlarePlugin.new(self, @lens_flares)
965
+ end
966
+
967
+ def create_window
968
+ # attributes = {
969
+ # alpha: _alpha,
970
+ # depth: _depth,
971
+ # stencil: _stencil,
972
+ # antialias: _antialias,
973
+ # premultiplied_alpha: _premultiplied_alpha,
974
+ # preserve_drawing_buffer: _preserve_drawing_buffer
975
+ # }
976
+
977
+ @window = GLFW::Window.new(@width, @height, @title, antialias: @antialias)
978
+
979
+ default_target.set_viewport_size(*(@window.framebuffer_size))
980
+
981
+ # TODO: handle losing opengl context??
982
+ end
983
+
984
+ def switch_geometry_program(program, material, geometry_group)
985
+ wireframe_bit = material.wireframe ? 1 : 0
986
+ geometry_program = "#{geometry_group.id}_#{program.id}_#{wireframe_bit}"
987
+
988
+ if geometry_program != @_current_geometry_program
989
+ @_current_geometry_program = geometry_program
990
+ true
991
+ else
992
+ false
993
+ end
994
+ end
995
+
996
+ def default_target
997
+ @_defualt_target ||= OpenGL::DefaultTarget.new(self)
998
+ end
999
+
1000
+ def update_camera_uniforms(uniforms, camera, material)
1001
+ GL.UniformMatrix4fv(uniforms['projectionMatrix'], 1, GL::FALSE, array_to_ptr_easy(camera.projection_matrix.elements))
1002
+
1003
+ if @logarithmic_depth_buffer
1004
+ GL.Uniform1f(uniforms['logDepthBuffFC'], 2.0 / ::Math.log(camera.far + 1.0) / Math::LN2)
1005
+ end
1006
+
1007
+ if material.needs_camera_position_uniform? && !uniforms['cameraPosition'].nil?
1008
+ @_vector3.set_from_matrix_position(camera.matrix_world)
1009
+ GL.Uniform3f(uniforms['cameraPosition'], @_vector3.x, @_vector3.y, @_vector3.z)
1010
+ end
1011
+
1012
+ if material.needs_view_matrix_uniform? && !uniforms['viewMatrix'].nil?
1013
+ GL.UniformMatrix4fv(uniforms['viewMatrix'], 1, GL::FALSE, array_to_ptr_easy(camera.matrix_world_inverse.elements))
1014
+ end
1015
+ end
1016
+
1017
+ def remove_child(object)
1018
+ if object.is_a?(Mesh) || object.is_a?(PointCloud) || object.is_a?(Line)
1019
+ @_opengl_objects.delete(object.id)
1020
+
1021
+ # elsif object.is_a?(ImmediateRenderObject) || object.immediate_render_callback
1022
+ # removeInstances( _webGL.ObjectsImmediate, object );
1023
+ end
1024
+
1025
+ object.deinit
1026
+ end
1027
+ end
1028
+ end