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,416 @@
1
+ require 'mittsu/math'
2
+
3
+ module Mittsu
4
+ class ShadowMapPlugin
5
+ def initialize(renderer, lights, opengl_objects, opengl_objects_immediate)
6
+ @renderer, @lights = renderer, lights
7
+ @opengl_objects = opengl_objects
8
+ @opengl_objects_immediate = opengl_objects_immediate
9
+
10
+ @frustum = Frustum.new
11
+ @proj_screen_matrix = Matrix4.new
12
+
13
+ @min = Vector3.new
14
+ @max = Vector3.new
15
+
16
+ @matrix_position = Vector3.new
17
+
18
+ @render_list = []
19
+
20
+ depth_shader = OpenGL::Shader::Lib[:depth_rgba]
21
+ depth_uniforms = OpenGL::Shader::UniformsUtils.clone(depth_shader.uniforms)
22
+
23
+ @depth_material = ShaderMaterial.new(
24
+ uniforms: depth_uniforms,
25
+ vertex_shader: depth_shader.vertex_shader,
26
+ fragment_shader: depth_shader.fragment_shader
27
+ )
28
+
29
+ @depth_material_morph = ShaderMaterial.new(
30
+ uniforms: depth_uniforms,
31
+ vertex_shader: depth_shader.vertex_shader,
32
+ fragment_shader: depth_shader.fragment_shader,
33
+ morph_targets: true
34
+ )
35
+
36
+ @depth_material_skin = ShaderMaterial.new(
37
+ uniforms: depth_uniforms,
38
+ vertex_shader: depth_shader.vertex_shader,
39
+ fragment_shader: depth_shader.fragment_shader,
40
+ skinning: true
41
+ )
42
+
43
+ @depth_material_morph_skin = ShaderMaterial.new(
44
+ uniforms: depth_uniforms,
45
+ vertex_shader: depth_shader.vertex_shader,
46
+ fragment_shader: depth_shader.fragment_shader,
47
+ morph_targets: true,
48
+ skinning: true
49
+ )
50
+
51
+ @depth_material.shadow_pass = true
52
+ @depth_material_morph.shadow_pass = true
53
+ @depth_material_skin.shadow_pass = true
54
+ @depth_material_morph_skin.shadow_pass = true
55
+ end
56
+
57
+ def render(scene, camera)
58
+ return unless @renderer.shadow_map_enabled
59
+
60
+ lights = []
61
+ fog = nil
62
+
63
+ # set GL state for depth map
64
+
65
+ GL.ClearColor(1.0, 1.0, 1.0, 1.0)
66
+ GL.Disable(GL::BLEND)
67
+
68
+ GL.Enable(GL::CULL_FACE)
69
+ GL.FrontFace(GL::CCW)
70
+
71
+ if @renderer.shadow_map_cull_face = CullFaceFront
72
+ GL.CullFace(GL::FRONT)
73
+ else
74
+ GL.CullFace(GL::BACK)
75
+ end
76
+
77
+ @renderer.state.set_depth_test(true)
78
+
79
+ # process lights
80
+ # - skip lights that are not casting shadows
81
+ # - create virtual lights for cascaded shadow maps
82
+
83
+ @lights.select(&:cast_shadow).each do |light|
84
+ if light.is_a?(DirectionalLight) && light.shadow_cascade
85
+ light.shadow_cascade_count.times do |n|
86
+ if !light.shadow_cascade_array[n]
87
+ virtual_light = create_virtual_light(light, n)
88
+ virtual_light.original_camera = camera
89
+
90
+ gyro = Gyroscope.new
91
+ gyro.position.copy(light.shadow_cascade_offset)
92
+
93
+ gyro.add(virtual_light)
94
+ gyro.add(virtual_light.target)
95
+
96
+ camera.add(gyro)
97
+
98
+ light.shadow_cascade_array[n] = virtual_light
99
+ else
100
+ virtual_light = light.shadow_cascade_array[n]
101
+ end
102
+
103
+ update_virtual_light(light, n)
104
+
105
+ lights << virtual_light
106
+ end
107
+ else
108
+ lights << light
109
+ end
110
+ end
111
+
112
+ # render depth map
113
+
114
+ lights.each do |light|
115
+ if !light.shadow_map
116
+ shadow_filter = LinearFilter
117
+ if @renderer.shadow_map_type == PCFSoftShadowMap
118
+ shadow_filter = NearestFilter
119
+ end
120
+
121
+ pars = { min_filter: shadow_filter, mag_filter: shadow_filter, format: RGBAFormat }
122
+
123
+ light.shadow_map = RenderTarget.new(light.shadow_map_width, light.shadow_map_height, pars)
124
+ light.shadow_map.renderer = @renderer
125
+ light.shadow_map_size = Vector2.new(light.shadow_map_width, light.shadow_map_height)
126
+
127
+ light.shadow_matrix = Matrix4.new
128
+ end
129
+
130
+ if !light.shadow_camera
131
+ case light
132
+ when SpotLight
133
+ light.shadow_camera = PerspectiveCamera.new(light.shadow_camera_fov, light.shadow_map_width / light.shadow_map_height, light.shadow_camera_near, light.shadow_camera_far)
134
+ when DirectionalLight
135
+ light.shadow_camera = OrthographicCamera.new(light.shadow_camera_left, light.shadow_camera_right, light.shadow_camera_top, light.shadow_camera_bottom, light.shadow_camera_near, light.shadow_camera_far)
136
+ else
137
+ puts "ERROR: Mittsu::ShadowMapPlugin: Unsupported light type for shadow #{light.inspect}"
138
+ next
139
+ end
140
+
141
+ scene.add(light.shadow_camera)
142
+ scene.update_matrix_world if scene.auto_update
143
+ end
144
+
145
+ if light.shadow_camera_visible && !light.camera_helper
146
+ light.camera_helper = CameraHelper.new(light.shadow_camera)
147
+ scene.add(light.camera_helper)
148
+ end
149
+
150
+ if light.virtual? && virtual_light.original_camera == camera
151
+ update_shadow_camera(camera, light)
152
+ end
153
+
154
+ shadow_map = light.shadow_map
155
+ shadow_matrix = light.shadow_matrix
156
+ shadow_camera = light.shadow_camera
157
+
158
+ #
159
+
160
+ shadow_camera.position.set_from_matrix_position(light.matrix_world)
161
+ @matrix_position.set_from_matrix_position(light.target.matrix_world)
162
+ shadow_camera.look_at(@matrix_position)
163
+ shadow_camera.update_matrix_world
164
+
165
+ shadow_camera.matrix_world_inverse.inverse(shadow_camera.matrix_world)
166
+
167
+ #
168
+
169
+
170
+ light.camera_helper.visible = light.shadow_camera_visible if light.camera_helper
171
+ light.camera_helper.update_points if light.shadow_camera_visible
172
+
173
+ # compute shadow matrix
174
+
175
+ shadow_matrix.set(
176
+ 0.5, 0.0, 0.0, 0.5,
177
+ 0.0, 0.5, 0.0, 0.5,
178
+ 0.0, 0.0, 0.5, 0.5,
179
+ 0.0, 0.0, 0.0, 1.0
180
+ )
181
+
182
+ shadow_matrix.multiply(shadow_camera.projection_matrix)
183
+ shadow_matrix.multiply(shadow_camera.matrix_world_inverse)
184
+
185
+ # update camera matrices and frustum
186
+
187
+ @proj_screen_matrix.multiply_matrices(shadow_camera.projection_matrix, shadow_camera.matrix_world_inverse)
188
+ @frustum.set_from_matrix(@proj_screen_matrix)
189
+
190
+ # render shadow map
191
+
192
+ @renderer.set_render_target(shadow_map)
193
+ @renderer.clear
194
+
195
+ # set object matrices & frustum culling
196
+
197
+ @render_list.clear
198
+
199
+ project_object(scene, scene, shadow_camera)
200
+
201
+ # render regular obejcts
202
+
203
+ @render_list.each do |opengl_object|
204
+ object = opengl_object[:object]
205
+ buffer = opengl_object[:buffer]
206
+
207
+ # culling is overridden globally for all objects
208
+ # while rendering depth map
209
+
210
+ # need to deal with MeshFaceMaterial somehow
211
+ # in that case just use the first of material.materials for now
212
+ # (proper solution would require to break objects by materials
213
+ # similarly to regular rendering and then set corresponding
214
+ # depth materials per each chunk instead of just once per object)
215
+
216
+ object_material = get_object_material(object)
217
+
218
+ # TODO: SkinnedMesh/morph_targets
219
+ # use_morphing = !object.geometry.morph_targets.nil? && !object.geometry.morph_targets.empty?
220
+ # use_skinning = object.is_a?(SkinnedMesh) && object_material.skinning
221
+
222
+ # TODO: SkinnedMesh/morph_targets
223
+ # if object.custom_depth_material
224
+ # material = object.custom_depth_material
225
+ # elsif use_skinning
226
+ # material = use_morphing ? @depth_material_morph_skin : @depth_material_skin
227
+ # elsif use_morphing
228
+ # material = @deptth_material_morph
229
+ # else
230
+ material = @depth_material
231
+ # end
232
+
233
+ @renderer.set_material_faces(object_material)
234
+
235
+ if buffer.is_a?(BufferGeometry)
236
+ @renderer.render_buffer_direct(shadow_camera, @lights, fog, material, buffer, object)
237
+ else
238
+ @renderer.render_buffer(shadow_camera, @lights, fog, material, buffer, object)
239
+ end
240
+ end
241
+
242
+ # set materices and rendr immeidate objects
243
+
244
+ @opengl_objects_immediate.each do |opengl_object_immediate|
245
+ opengl_object = opengl_object_immediate
246
+ object = opengl_object[:object]
247
+
248
+ if object.visible && object.cast_shadow
249
+ object[:_model_view_matrix].multiply_matrices(shadow_camera.matrix_womatrix_world_inverse, object.matrix_world)
250
+ @renderer.render_immediate_object(shadow_camera, @lights, fog, @depth_material, object)
251
+ end
252
+ end
253
+ end
254
+
255
+ # restore GL state
256
+
257
+ clear_color = @renderer.get_clear_color
258
+ clear_alpha = @renderer.get_clear_alpha
259
+
260
+ GL.ClearColor(clear_color.r, clear_color.g, clear_color.b, clear_alpha)
261
+ GL.Enable(GL::BLEND)
262
+
263
+ if @renderer.shadow_map_cull_face == CullFaceFront
264
+ GL.CullFace(GL::BACK)
265
+ end
266
+
267
+ @renderer.reset_gl_state
268
+ end
269
+
270
+ def project_object(scene, object, shadow_camera)
271
+ if object.visible
272
+ opengl_objects = @opengl_objects[object.id]
273
+
274
+ if opengl_objects && object.cast_shadow && (object.frustum_culled == false || @frustum.intersects_object?(object) == true)
275
+ opengl_objects.each do |opengl_object|
276
+ object.model_view_matrix.multiply_matrices(shadow_camera.matrix_world_inverse, object.matrix_world)
277
+ @render_list << opengl_object
278
+ end
279
+ end
280
+
281
+ object.children.each do |child|
282
+ project_object(scene, child, shadow_camera)
283
+ end
284
+ end
285
+ end
286
+
287
+ def create_virtual_light(light, cascade)
288
+ DirectionalLight.new.tap do |virtual_light|
289
+ virtual_light.is_virtual = true
290
+
291
+ virtual_light.only_shadow = true
292
+ virtual_light.cast_shadow = true
293
+
294
+ virtual_light.shadow_camera_near = light.shadow_camera_near
295
+ virtual_light.shadow_camera_far = light.shadow_camera_far
296
+
297
+ virtual_light.shadow_camera_left = light.shadow_camera_left
298
+ virtual_light.shadow_camera_right = light.shadow_camera_right
299
+ virtual_light.shadow_camera_bottom = light.shadow_camera_bottom
300
+ virtual_light.shadow_camera_top = light.shadow_camera_top
301
+
302
+ virtual_light.shadow_camera_visible = light.shadow_camera_visible
303
+
304
+ virtual_light.shadow_darkness = light.shadow_darkness
305
+
306
+ virtual_light.shadow_darkness = light.shadow_darkness
307
+
308
+ virtual_light.shadow_bias = light.shadow_cascade_bias[cascade]
309
+ virtual_light.shadow_map_width = light.shadow_cascade_width[cascade]
310
+ virtual_light.shadow_map_height = light.shadow_cascade_height[cascade]
311
+
312
+ points_world = virtual_light.points_world = []
313
+ points_frustum = virtual_light.points_frustum = []
314
+
315
+ 8.times do
316
+ points_world << Vector3.new
317
+ points_frustum << Vector3.new
318
+ end
319
+
320
+ near_z = light.shadow_cascade_near_z[cascade]
321
+ far_z = light.shadow_cascade_far_z[cascade]
322
+
323
+ points_frustum[0].set(-1.0, -1.0, near_z)
324
+ points_frustum[1].set( 1.0, -1.0, near_z)
325
+ points_frustum[2].set(-1.0, 1.0, near_z)
326
+ points_frustum[3].set( 1.0, 1.0, near_z)
327
+
328
+ points_frustum[4].set(-1.0, -1.0, far_z)
329
+ points_frustum[5].set( 1.0, -1.0, far_z)
330
+ points_frustum[6].set(-1.0, 1.0, far_z)
331
+ points_frustum[7].set( 1.0, 1.0, far_z)
332
+ end
333
+ end
334
+
335
+ # synchronize virtual light with the original light
336
+
337
+ def update_virtual_light(light, cascade)
338
+ virtual_light = light.shadow_cascade_array[cascade]
339
+
340
+ virtual_light.position.copy(light.position)
341
+ virtual_light.target.position.copy(light.target.position)
342
+ virtual_light.look_at(virtual_light.target)
343
+
344
+ virtual_light.shadow_camera_visible = light.shadow_camera_visible
345
+ virtual_light.shadow_darkness = light.shadow_darkness
346
+
347
+ virtual_light.shadow_bias = light.shadow_cascade_bias[cascade]
348
+
349
+ near_z = light.shadow_cascade_near_z[cascade]
350
+ far_z = light.shadow_cascade_far_z[cascade]
351
+
352
+ points_frustum = virtual_light.points_frustum
353
+
354
+ points_frustum[0].z = near_z
355
+ points_frustum[1].z = near_z
356
+ points_frustum[2].z = near_z
357
+ points_frustum[3].z = near_z
358
+
359
+ points_frustum[4].z = far_z
360
+ points_frustum[5].z = far_z
361
+ points_frustum[6].z = far_z
362
+ points_frustum[7].z = far_z
363
+ end
364
+
365
+ # fit shadow camera's ortho frustum to camera frustum
366
+
367
+ def update_shadow_camera(camera, light)
368
+ shadow_camera = light.shadow_camera
369
+ points_frustum = light.pointa_frustum
370
+ points_world = light.points_world
371
+
372
+ @min.set(Float::INFINITY, Float::INFINITY, Float::INFINITY)
373
+ @max.set(-Float::INFINITY, -Float::INFINITY, -Float::INFINITY)
374
+
375
+ 8.times do |i|
376
+ p = points_world[i]
377
+
378
+ p.copy(points_frustum[i])
379
+ p.unproject(camera)
380
+
381
+ p.apply_matrix4(shadow_camera.matrix_world_inverse)
382
+
383
+ @min.x = p.x if (p.x < @min.x)
384
+ @max.x = p.x if (p.x > @max.x)
385
+
386
+ @min.y = p.y if (p.y < @min.y)
387
+ @max.y = p.y if (p.y > @max.y)
388
+
389
+ @min.z = p.z if (p.z < @min.z)
390
+ @max.z = p.z if (p.z > @max.z)
391
+ end
392
+
393
+ shadow_camera.left = @min.x
394
+ shadow_camera.right = @max.x
395
+ shadow_camera.top = @max.y
396
+ shadow_camera.bottom = @min.y
397
+
398
+ # can't really fit near/far
399
+ # shadow_camera.near = @min.x
400
+ # shadow_camera.far = @max.z
401
+
402
+ shadow_camera.update_projection_matrix
403
+ end
404
+
405
+ # For the moment just ignore objects that have multiple materials with different animation methods
406
+ # Only the frst material will be taken into account for deciding which depth material to use for shadow maps
407
+
408
+ def get_object_material(object)
409
+ if object.material.is_a?(MeshFaceMaterial)
410
+ object.material.materials[0]
411
+ else
412
+ object.material
413
+ end
414
+ end
415
+ end
416
+ end
@@ -0,0 +1,38 @@
1
+ #version 330
2
+
3
+ uniform vec3 color;
4
+ uniform sampler2D map;
5
+ uniform float opacity;
6
+
7
+ uniform int fogType;
8
+ uniform vec3 fogColor;
9
+ uniform float fogDensity;
10
+ uniform float fogNear;
11
+ uniform float fogFar;
12
+ uniform float alphaTest;
13
+
14
+ in vec2 vUV;
15
+ layout(location = 0) out vec4 fragColor;
16
+
17
+ void main() {
18
+ vec4 texture = texture( map, vUV );
19
+
20
+ if ( texture.a < alphaTest ) discard;
21
+
22
+ fragColor = vec4( color * texture.xyz, texture.a * opacity );
23
+
24
+ if ( fogType > 0 ) {
25
+ float depth = gl_FragCoord.z / gl_FragCoord.w;
26
+ float fogFactor = 0.0;
27
+
28
+ if ( fogType == 1 ) {
29
+ fogFactor = smoothstep( fogNear, fogFar, depth );
30
+ } else {
31
+ const float LOG2 = 1.442695;
32
+ float fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );
33
+ fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );
34
+ }
35
+
36
+ fragColor = mix( fragColor, vec4( fogColor, fragColor.w ), fogFactor );
37
+ }
38
+ }
@@ -0,0 +1,250 @@
1
+ module Mittsu
2
+ class SpritePlugin
3
+ include OpenGL::Helper
4
+
5
+ VERTICES = [
6
+ -0.5, -0.5, 0.0, 0.0,
7
+ 0.5, -0.5, 1.0, 0.0,
8
+ 0.5, 0.5, 1.0, 1.0,
9
+ -0.5, 0.5, 0.0, 1.0
10
+ ] # Float32Array
11
+
12
+ FACES = [
13
+ 0, 1, 2,
14
+ 0, 2, 3
15
+ ] # Uint16Array
16
+
17
+ def initialize(renderer, sprites)
18
+ @renderer = renderer
19
+ @sprites = sprites
20
+ @program = nil
21
+
22
+ # for decomposing matrixWorld
23
+ @sprite_position = Vector3.new
24
+ @sprite_rotation = Quaternion.new
25
+ @sprite_scale = Vector3.new
26
+ end
27
+
28
+ def render(scene, camera)
29
+ return if @sprites.empty?
30
+
31
+ init if @program.nil?
32
+ setup_gl_for_render(camera)
33
+ setup_fog(scene)
34
+
35
+ update_positions_and_sort(camera)
36
+
37
+ render_all_sprites(scene)
38
+
39
+ GL.Enable(GL::CULL_FACE)
40
+ @renderer.reset_gl_state
41
+ end
42
+
43
+ private
44
+
45
+ def init
46
+ create_vertex_array_object
47
+ create_program
48
+
49
+ init_attributes
50
+ init_uniforms
51
+
52
+ # TODO: canvas texture??
53
+ end
54
+
55
+ def create_vertex_array_object
56
+ @vertex_array_object = GL.CreateVertexArray
57
+ GL.BindVertexArray(@vertex_array_object)
58
+
59
+ @vertex_buffer = GL.CreateBuffer
60
+ @element_buffer = GL.CreateBuffer
61
+
62
+ GL.BindBuffer(GL::ARRAY_BUFFER, @vertex_buffer)
63
+ GL.BufferData_easy(GL::ARRAY_BUFFER, VERTICES, GL::STATIC_DRAW)
64
+
65
+ GL.BindBuffer(GL::ELEMENT_ARRAY_BUFFER, @element_buffer)
66
+ GL.BufferData_easy(GL::ELEMENT_ARRAY_BUFFER, FACES, GL::STATIC_DRAW)
67
+ end
68
+
69
+ def create_program
70
+ @program = GL.CreateProgram
71
+
72
+ vertex_shader = OpenGL::Shader.new(GL::VERTEX_SHADER, File.read(File.join(__dir__, 'sprite_vertex.glsl')))
73
+ fragment_shader = OpenGL::Shader.new(GL::FRAGMENT_SHADER, File.read(File.join(__dir__, 'sprite_fragment.glsl')))
74
+
75
+ GL.AttachShader(@program, vertex_shader.shader)
76
+ GL.AttachShader(@program, fragment_shader.shader)
77
+
78
+ GL.LinkProgram(@program)
79
+ end
80
+
81
+ def init_attributes
82
+ @attributes = {
83
+ position: GL.GetAttribLocation(@program, 'position'),
84
+ uv: GL.GetAttribLocation(@program, 'uv')
85
+ }
86
+ end
87
+
88
+ def init_uniforms
89
+ @uniforms = {
90
+ uvOffset: GL.GetUniformLocation(@program, 'uvOffset'),
91
+ uvScale: GL.GetUniformLocation(@program, 'uvScale'),
92
+
93
+ rotation: GL.GetUniformLocation(@program, 'rotation'),
94
+ scale: GL.GetUniformLocation(@program, 'scale'),
95
+
96
+ color: GL.GetUniformLocation(@program, 'color'),
97
+ map: GL.GetUniformLocation(@program, 'map'),
98
+ opacity: GL.GetUniformLocation(@program, 'opacity'),
99
+
100
+ modelViewMatrix: GL.GetUniformLocation(@program, 'modelViewMatrix'),
101
+ projectionMatrix: GL.GetUniformLocation(@program, 'projectionMatrix'),
102
+
103
+ fogType: GL.GetUniformLocation(@program, 'fogType'),
104
+ fogDensity: GL.GetUniformLocation(@program, 'fogDensity'),
105
+ fogNear: GL.GetUniformLocation(@program, 'fogNear'),
106
+ fogFar: GL.GetUniformLocation(@program, 'fogFar'),
107
+ fogColor: GL.GetUniformLocation(@program, 'fogColor'),
108
+
109
+ alphaTest: GL.GetUniformLocation(@program, 'alphaTest')
110
+ }
111
+ end
112
+
113
+ def painter_sort_stable(a, b)
114
+ if a.z != b.z
115
+ b.z - a.z
116
+ else
117
+ b.id - a.id
118
+ end
119
+ end
120
+
121
+ def setup_gl_for_render(camera)
122
+ GL.UseProgram(@program)
123
+
124
+ GL.Disable(GL::CULL_FACE)
125
+ GL.Enable(GL::BLEND)
126
+
127
+ GL.BindVertexArray(@vertex_array_object)
128
+
129
+ GL.EnableVertexAttribArray(@attributes[:position])
130
+ GL.EnableVertexAttribArray(@attributes[:uv])
131
+
132
+ GL.BindBuffer(GL::ARRAY_BUFFER, @vertex_buffer)
133
+
134
+ GL.VertexAttribPointer(@attributes[:position], 2, GL::FLOAT, GL::FALSE, 2 * 8, 0)
135
+ GL.VertexAttribPointer(@attributes[:uv], 2, GL::FLOAT, GL::FALSE, 2 * 8, 8)
136
+
137
+ GL.BindBuffer(GL::ELEMENT_ARRAY_BUFFER, @element_buffer)
138
+
139
+ GL.UniformMatrix4fv(@uniforms[:projectionMatrix], 1, GL::FALSE, array_to_ptr_easy(camera.projection_matrix.elements))
140
+
141
+ GL.ActiveTexture(GL::TEXTURE0)
142
+ GL.Uniform1i(@uniforms[:map], 0)
143
+ end
144
+
145
+ def setup_fog(scene)
146
+ @old_fog_type = 0
147
+ @scene_fog_type = 0
148
+ fog = scene.fog
149
+
150
+ if fog
151
+ GL.Uniform3f(@uniforms[:fogColor], fog.color.r, fog.color.g, fog.color.b)
152
+
153
+ if fog.is_a?(Fog)
154
+ GL.Uniform1f(@uniforms[:fogNear], fog.near)
155
+ GL.Uniform1f(@uniforms[:fogFar], fog.far)
156
+
157
+ GL.Uniform1i(@uniforms[:fogType], 1)
158
+ @old_fog_type = 1
159
+ @scene_fog_type = 1
160
+ elsif fog.is_a?(FogExp2)
161
+ GL.Uniform1f(@uniforms[:fogDensity], fog.density)
162
+
163
+ GL.Uniform1i(@uniforms[:fogType], 2)
164
+ @old_fog_type = 2
165
+ @scene_fog_type = 2
166
+ end
167
+ else
168
+ GL.Uniform1i(@uniforms[:fogType], 0)
169
+ @old_fog_type = 0
170
+ @scene_fog_type = 0
171
+ end
172
+ end
173
+
174
+ def update_positions_and_sort(camera)
175
+ @sprites.each do |sprite|
176
+ sprite.model_view_matrix.multiply_matrices(camera.matrix_world_inverse, sprite.matrix_world)
177
+ sprite.z = -sprite.model_view_matrix.elements[14]
178
+ end
179
+
180
+ @sprites.sort!(&self.method(:painter_sort_stable))
181
+ end
182
+
183
+ def render_all_sprites(scene)
184
+ @sprites.each do |sprite|
185
+ material = sprite.material
186
+
187
+ set_fog_uniforms(material, scene)
188
+ set_uv_uniforms(material)
189
+ set_color_uniforms(material)
190
+ set_transform_uniforms(sprite)
191
+ set_blend_mode(material)
192
+
193
+ # set texture
194
+ if material.map && material.map.image && material.map.image.width
195
+ material.map.set(0, @renderer)
196
+ else
197
+ # TODO: canvas texture?
198
+ # texture.set(0, @renderer)
199
+ end
200
+
201
+ # draw elements
202
+ GL.DrawElements(GL::TRIANGLES, 6, GL::UNSIGNED_INT, 0) # GL::UNSIGNED_SHORT
203
+ end
204
+ end
205
+
206
+ def set_fog_uniforms(material, scene)
207
+ fog_type = 0
208
+
209
+ if scene.fog && material.fog
210
+ fog_type = @scene_fog_type
211
+ end
212
+
213
+ if @old_fog_type != fog_type
214
+ GL.Uniform1(@uniforms[:fogType], fog_type)
215
+ @old_fog_type = fog_type
216
+ end
217
+ end
218
+
219
+ def set_uv_uniforms(material)
220
+ if !material.map.nil?
221
+ GL.Uniform2f(@uniforms[:uvOffset], material.map.offset.x, material.map.offset.y)
222
+ GL.Uniform2f(@uniforms[:uvScale], material.map.repeat.x, material.map.repeat.y)
223
+ else
224
+ GL.Uniform2f(@uniforms[:uvOffset], 0.0, 0.0)
225
+ GL.Uniform2f(@uniforms[:uvScale], 1.0, 1.0)
226
+ end
227
+ end
228
+
229
+ def set_color_uniforms(material)
230
+ GL.Uniform1f(@uniforms[:opacity], material.opacity)
231
+ GL.Uniform3f(@uniforms[:color], material.color.r, material.color.g, material.color.b)
232
+ GL.Uniform1f(@uniforms[:alphaTest], material.alpha_test)
233
+ end
234
+
235
+ def set_transform_uniforms(sprite)
236
+ GL.UniformMatrix4fv(@uniforms[:modelViewMatrix], 1, GL::FALSE, array_to_ptr_easy(sprite.model_view_matrix.elements))
237
+
238
+ sprite.matrix_world.decompose(@sprite_position, @sprite_rotation, @sprite_scale)
239
+
240
+ GL.Uniform1f(@uniforms[:rotation], sprite.material.rotation)
241
+ GL.Uniform2fv(@uniforms[:scale], 1, array_to_ptr_easy([@sprite_scale.x, @sprite_scale.y]))
242
+ end
243
+
244
+ def set_blend_mode(material)
245
+ @renderer.state.set_blending(material.blending, material.blend_equation, material.blend_src, material.blend_dst)
246
+ @renderer.state.set_depth_test(material.depth_test)
247
+ @renderer.state.set_depth_write(material.depth_write)
248
+ end
249
+ end
250
+ end