3rb 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +2 -0
  3. data/3rb.gemspec +29 -0
  4. data/CHANGELOG.md +12 -0
  5. data/LICENSE +21 -0
  6. data/README.md +321 -0
  7. data/Rakefile +13 -0
  8. data/examples/01_hello_cube.rb +29 -0
  9. data/examples/02_basic_geometries.rb +56 -0
  10. data/examples/03_materials.rb +61 -0
  11. data/examples/04_lighting.rb +63 -0
  12. data/examples/05_animation.rb +79 -0
  13. data/examples/06_custom_shader.rb +92 -0
  14. data/examples/07_scene_graph.rb +74 -0
  15. data/examples/08_orbit_controls.rb +50 -0
  16. data/examples/09_3d_chart.rb +71 -0
  17. data/examples/10_procedural_terrain.rb +140 -0
  18. data/examples/11_particle_system.rb +68 -0
  19. data/examples/12_model_loader.rb +73 -0
  20. data/examples/13_game_prototype.rb +145 -0
  21. data/examples/14_utah_teapot.rb +291 -0
  22. data/examples/15_stanford_bunny.rb +200 -0
  23. data/examples/16_cornell_box.rb +373 -0
  24. data/examples/17_weird_fractal4.rb +130 -0
  25. data/examples/18_platonic_solids.rb +268 -0
  26. data/lib/3rb/animation/animation_clip.rb +287 -0
  27. data/lib/3rb/animation/animation_mixer.rb +366 -0
  28. data/lib/3rb/cameras/camera.rb +50 -0
  29. data/lib/3rb/cameras/orthographic_camera.rb +92 -0
  30. data/lib/3rb/cameras/perspective_camera.rb +103 -0
  31. data/lib/3rb/controls/orbit_controls.rb +341 -0
  32. data/lib/3rb/core/buffer_attribute.rb +172 -0
  33. data/lib/3rb/core/group.rb +9 -0
  34. data/lib/3rb/core/object3d.rb +298 -0
  35. data/lib/3rb/core/scene.rb +78 -0
  36. data/lib/3rb/dsl/helpers.rb +57 -0
  37. data/lib/3rb/dsl/scene_builder.rb +288 -0
  38. data/lib/3rb/ffi/glfw.rb +61 -0
  39. data/lib/3rb/ffi/opengl.rb +137 -0
  40. data/lib/3rb/ffi/platform.rb +65 -0
  41. data/lib/3rb/geometries/box_geometry.rb +101 -0
  42. data/lib/3rb/geometries/buffer_geometry.rb +345 -0
  43. data/lib/3rb/geometries/cone_geometry.rb +29 -0
  44. data/lib/3rb/geometries/cylinder_geometry.rb +149 -0
  45. data/lib/3rb/geometries/plane_geometry.rb +75 -0
  46. data/lib/3rb/geometries/sphere_geometry.rb +93 -0
  47. data/lib/3rb/geometries/torus_geometry.rb +77 -0
  48. data/lib/3rb/lights/ambient_light.rb +9 -0
  49. data/lib/3rb/lights/directional_light.rb +57 -0
  50. data/lib/3rb/lights/hemisphere_light.rb +26 -0
  51. data/lib/3rb/lights/light.rb +27 -0
  52. data/lib/3rb/lights/point_light.rb +68 -0
  53. data/lib/3rb/lights/rect_area_light.rb +35 -0
  54. data/lib/3rb/lights/spot_light.rb +88 -0
  55. data/lib/3rb/loaders/gltf_loader.rb +304 -0
  56. data/lib/3rb/loaders/loader.rb +94 -0
  57. data/lib/3rb/loaders/obj_loader.rb +186 -0
  58. data/lib/3rb/loaders/texture_loader.rb +55 -0
  59. data/lib/3rb/materials/basic_material.rb +70 -0
  60. data/lib/3rb/materials/lambert_material.rb +102 -0
  61. data/lib/3rb/materials/material.rb +114 -0
  62. data/lib/3rb/materials/phong_material.rb +106 -0
  63. data/lib/3rb/materials/shader_material.rb +104 -0
  64. data/lib/3rb/materials/standard_material.rb +106 -0
  65. data/lib/3rb/math/color.rb +246 -0
  66. data/lib/3rb/math/euler.rb +156 -0
  67. data/lib/3rb/math/math_utils.rb +132 -0
  68. data/lib/3rb/math/matrix3.rb +269 -0
  69. data/lib/3rb/math/matrix4.rb +501 -0
  70. data/lib/3rb/math/quaternion.rb +337 -0
  71. data/lib/3rb/math/vector2.rb +216 -0
  72. data/lib/3rb/math/vector3.rb +366 -0
  73. data/lib/3rb/math/vector4.rb +233 -0
  74. data/lib/3rb/native/gl.rb +382 -0
  75. data/lib/3rb/native/native.rb +55 -0
  76. data/lib/3rb/native/window.rb +111 -0
  77. data/lib/3rb/native.rb +9 -0
  78. data/lib/3rb/objects/line.rb +116 -0
  79. data/lib/3rb/objects/mesh.rb +40 -0
  80. data/lib/3rb/objects/points.rb +71 -0
  81. data/lib/3rb/renderers/opengl_renderer.rb +567 -0
  82. data/lib/3rb/renderers/renderer.rb +60 -0
  83. data/lib/3rb/renderers/shader_lib.rb +100 -0
  84. data/lib/3rb/textures/cube_texture.rb +26 -0
  85. data/lib/3rb/textures/data_texture.rb +35 -0
  86. data/lib/3rb/textures/render_target.rb +125 -0
  87. data/lib/3rb/textures/texture.rb +190 -0
  88. data/lib/3rb/version.rb +5 -0
  89. data/lib/3rb.rb +86 -0
  90. data/shaders/basic.frag +19 -0
  91. data/shaders/basic.vert +15 -0
  92. data/shaders/common/lights.glsl +53 -0
  93. data/shaders/common/uniforms.glsl +9 -0
  94. data/shaders/lambert.frag +37 -0
  95. data/shaders/lambert.vert +22 -0
  96. data/shaders/phong.frag +51 -0
  97. data/shaders/phong.vert +28 -0
  98. data/shaders/standard.frag +92 -0
  99. data/shaders/standard.vert +28 -0
  100. metadata +155 -0
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sunrb
4
+ module ShaderLib
5
+ SHADERS_PATH = File.expand_path("../../../shaders", __dir__)
6
+
7
+ class << self
8
+ def load_shader(name)
9
+ {
10
+ vertex_shader: load_file("#{name}.vert"),
11
+ fragment_shader: load_file("#{name}.frag")
12
+ }
13
+ end
14
+
15
+ def basic
16
+ @basic ||= load_shader("basic").merge(
17
+ uniforms: basic_uniforms
18
+ )
19
+ end
20
+
21
+ def lambert
22
+ @lambert ||= load_shader("lambert").merge(
23
+ uniforms: lambert_uniforms
24
+ )
25
+ end
26
+
27
+ def phong
28
+ @phong ||= load_shader("phong").merge(
29
+ uniforms: phong_uniforms
30
+ )
31
+ end
32
+
33
+ def standard
34
+ @standard ||= load_shader("standard").merge(
35
+ uniforms: standard_uniforms
36
+ )
37
+ end
38
+
39
+ private
40
+
41
+ def load_file(filename)
42
+ path = File.join(SHADERS_PATH, filename)
43
+ return nil unless File.exist?(path)
44
+
45
+ File.read(path)
46
+ end
47
+
48
+ def common_uniforms
49
+ {
50
+ model_matrix: { type: :mat4, value: nil },
51
+ model_view_matrix: { type: :mat4, value: nil },
52
+ projection_matrix: { type: :mat4, value: nil },
53
+ view_matrix: { type: :mat4, value: nil },
54
+ normal_matrix: { type: :mat3, value: nil },
55
+ camera_position: { type: :vec3, value: Vector3.new }
56
+ }
57
+ end
58
+
59
+ def basic_uniforms
60
+ common_uniforms.merge(
61
+ diffuse: { type: :vec3, value: Color.new(0xffffff) },
62
+ opacity: { type: :float, value: 1.0 },
63
+ map: { type: :texture, value: nil },
64
+ use_map: { type: :bool, value: false }
65
+ )
66
+ end
67
+
68
+ def lambert_uniforms
69
+ basic_uniforms.merge(
70
+ emissive: { type: :vec3, value: Color.new(0x000000) },
71
+ ambient_light_color: { type: :vec3, value: Color.new(0x000000) },
72
+ directional_light_direction: { type: :vec3, value: Vector3.new(0, 1, 0) },
73
+ directional_light_color: { type: :vec3, value: Color.new(0xffffff) }
74
+ )
75
+ end
76
+
77
+ def phong_uniforms
78
+ lambert_uniforms.merge(
79
+ specular: { type: :vec3, value: Color.new(0x111111) },
80
+ shininess: { type: :float, value: 30.0 }
81
+ )
82
+ end
83
+
84
+ def standard_uniforms
85
+ common_uniforms.merge(
86
+ diffuse: { type: :vec3, value: Color.new(0xffffff) },
87
+ emissive: { type: :vec3, value: Color.new(0x000000) },
88
+ roughness: { type: :float, value: 1.0 },
89
+ metalness: { type: :float, value: 0.0 },
90
+ opacity: { type: :float, value: 1.0 },
91
+ map: { type: :texture, value: nil },
92
+ use_map: { type: :bool, value: false },
93
+ ambient_light_color: { type: :vec3, value: Color.new(0x000000) },
94
+ directional_light_direction: { type: :vec3, value: Vector3.new(0, 1, 0) },
95
+ directional_light_color: { type: :vec3, value: Color.new(0xffffff) }
96
+ )
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sunrb
4
+ class CubeTexture < Texture
5
+ attr_accessor :images
6
+
7
+ def initialize(
8
+ images: Array.new(6),
9
+ mapping: :cube_reflection,
10
+ **options
11
+ )
12
+ super(mapping: mapping, **options)
13
+
14
+ @images = images
15
+ @flip_y = false
16
+ end
17
+
18
+ def image
19
+ @images
20
+ end
21
+
22
+ def image=(value)
23
+ @images = value
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sunrb
4
+ class DataTexture < Texture
5
+ attr_accessor :data, :width, :height
6
+
7
+ def initialize(
8
+ data: nil,
9
+ width: 1,
10
+ height: 1,
11
+ format: :rgba,
12
+ type: :unsigned_byte,
13
+ **options
14
+ )
15
+ super(format: format, type: type, **options)
16
+
17
+ @data = data
18
+ @width = width
19
+ @height = height
20
+
21
+ @mag_filter = :nearest
22
+ @min_filter = :nearest
23
+
24
+ @generate_mipmaps = false
25
+ @flip_y = false
26
+ @unpack_alignment = 1
27
+
28
+ @needs_update = true
29
+ end
30
+
31
+ def image
32
+ { data: @data, width: @width, height: @height }
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sunrb
4
+ class RenderTarget
5
+ attr_accessor :uuid, :width, :height, :depth
6
+ attr_accessor :scissor, :scissor_test
7
+ attr_accessor :viewport
8
+ attr_accessor :texture, :depth_buffer, :stencil_buffer
9
+ attr_accessor :depth_texture
10
+
11
+ def initialize(
12
+ width: 1,
13
+ height: 1,
14
+ depth: 1,
15
+ min_filter: :linear,
16
+ mag_filter: :linear,
17
+ wrap_s: :clamp_to_edge,
18
+ wrap_t: :clamp_to_edge,
19
+ generate_mipmaps: false,
20
+ format: :rgba,
21
+ type: :unsigned_byte,
22
+ anisotropy: 1,
23
+ encoding: :linear,
24
+ depth_buffer: true,
25
+ stencil_buffer: false,
26
+ depth_texture: nil
27
+ )
28
+ @uuid = SecureRandom.uuid
29
+ @width = width
30
+ @height = height
31
+ @depth = depth
32
+
33
+ @scissor = Vector4.new(0, 0, width, height)
34
+ @scissor_test = false
35
+
36
+ @viewport = Vector4.new(0, 0, width, height)
37
+
38
+ @texture = Texture.new(
39
+ mag_filter: mag_filter,
40
+ min_filter: min_filter,
41
+ wrap_s: wrap_s,
42
+ wrap_t: wrap_t,
43
+ format: format,
44
+ type: type,
45
+ anisotropy: anisotropy
46
+ )
47
+ @texture.generate_mipmaps = generate_mipmaps
48
+ @texture.encoding = encoding
49
+
50
+ @depth_buffer = depth_buffer
51
+ @stencil_buffer = stencil_buffer
52
+ @depth_texture = depth_texture
53
+ end
54
+
55
+ def set_size(width, height, depth = 1)
56
+ return if @width == width && @height == height && @depth == depth
57
+
58
+ @width = width
59
+ @height = height
60
+ @depth = depth
61
+
62
+ @texture.needs_update = true
63
+
64
+ dispose
65
+ end
66
+
67
+ def clone
68
+ self.class.new.copy(self)
69
+ end
70
+
71
+ def copy(source)
72
+ @width = source.width
73
+ @height = source.height
74
+ @depth = source.depth
75
+
76
+ @viewport.copy(source.viewport)
77
+
78
+ @texture = source.texture.clone
79
+
80
+ @depth_buffer = source.depth_buffer
81
+ @stencil_buffer = source.stencil_buffer
82
+ @depth_texture = source.depth_texture&.clone
83
+
84
+ self
85
+ end
86
+
87
+ def dispose
88
+ @texture.version += 1
89
+ end
90
+ end
91
+
92
+ class WebGLRenderTarget < RenderTarget
93
+ end
94
+
95
+ class WebGLMultipleRenderTargets < RenderTarget
96
+ attr_accessor :textures
97
+
98
+ def initialize(width: 1, height: 1, count: 1, **options)
99
+ super(width: width, height: height, **options)
100
+
101
+ @textures = Array.new(count) do
102
+ Texture.new(
103
+ mag_filter: options[:mag_filter] || :linear,
104
+ min_filter: options[:min_filter] || :linear,
105
+ wrap_s: options[:wrap_s] || :clamp_to_edge,
106
+ wrap_t: options[:wrap_t] || :clamp_to_edge,
107
+ format: options[:format] || :rgba,
108
+ type: options[:type] || :unsigned_byte
109
+ )
110
+ end
111
+ end
112
+
113
+ def set_size(width, height, depth = 1)
114
+ return if @width == width && @height == height && @depth == depth
115
+
116
+ @width = width
117
+ @height = height
118
+ @depth = depth
119
+
120
+ @textures.each { |t| t.needs_update = true }
121
+
122
+ dispose
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,190 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sunrb
4
+ class Texture
5
+ MAPPING = {
6
+ uv: 300,
7
+ cube_reflection: 301,
8
+ cube_refraction: 302,
9
+ equirectangular_reflection: 303,
10
+ equirectangular_refraction: 304,
11
+ spherical_reflection: 305
12
+ }.freeze
13
+
14
+ WRAPPING = {
15
+ repeat: 1000,
16
+ clamp_to_edge: 1001,
17
+ mirrored_repeat: 1002
18
+ }.freeze
19
+
20
+ FILTER = {
21
+ nearest: 1003,
22
+ nearest_mipmap_nearest: 1004,
23
+ nearest_mipmap_linear: 1005,
24
+ linear: 1006,
25
+ linear_mipmap_nearest: 1007,
26
+ linear_mipmap_linear: 1008
27
+ }.freeze
28
+
29
+ FORMAT = {
30
+ alpha: 1021,
31
+ rgb: 1022,
32
+ rgba: 1023,
33
+ luminance: 1024,
34
+ luminance_alpha: 1025,
35
+ depth: 1026,
36
+ depth_stencil: 1027
37
+ }.freeze
38
+
39
+ TYPE = {
40
+ unsigned_byte: 1009,
41
+ byte: 1010,
42
+ short: 1011,
43
+ unsigned_short: 1012,
44
+ int: 1013,
45
+ unsigned_int: 1014,
46
+ float: 1015,
47
+ half_float: 1016
48
+ }.freeze
49
+
50
+ attr_accessor :uuid, :name, :image, :mipmaps
51
+ attr_accessor :mapping, :wrap_s, :wrap_t
52
+ attr_accessor :mag_filter, :min_filter
53
+ attr_accessor :anisotropy
54
+ attr_accessor :format, :internal_format, :type
55
+ attr_accessor :offset, :repeat, :center, :rotation
56
+ attr_accessor :matrix_auto_update, :matrix
57
+ attr_accessor :generate_mipmaps, :premultiply_alpha, :flip_y
58
+ attr_accessor :unpack_alignment, :encoding
59
+ attr_accessor :version, :needs_update
60
+ attr_accessor :user_data
61
+
62
+ def initialize(
63
+ image: nil,
64
+ mapping: :uv,
65
+ wrap_s: :clamp_to_edge,
66
+ wrap_t: :clamp_to_edge,
67
+ mag_filter: :linear,
68
+ min_filter: :linear_mipmap_linear,
69
+ format: :rgba,
70
+ type: :unsigned_byte,
71
+ anisotropy: 1
72
+ )
73
+ @uuid = SecureRandom.uuid
74
+ @name = ""
75
+ @image = image
76
+ @mipmaps = []
77
+
78
+ @mapping = mapping
79
+ @wrap_s = wrap_s
80
+ @wrap_t = wrap_t
81
+
82
+ @mag_filter = mag_filter
83
+ @min_filter = min_filter
84
+
85
+ @anisotropy = anisotropy
86
+
87
+ @format = format
88
+ @internal_format = nil
89
+ @type = type
90
+
91
+ @offset = Vector2.new(0, 0)
92
+ @repeat = Vector2.new(1, 1)
93
+ @center = Vector2.new(0, 0)
94
+ @rotation = 0
95
+
96
+ @matrix_auto_update = true
97
+ @matrix = Matrix3.new
98
+
99
+ @generate_mipmaps = true
100
+ @premultiply_alpha = false
101
+ @flip_y = true
102
+ @unpack_alignment = 4
103
+
104
+ @encoding = :linear
105
+ @version = 0
106
+ @needs_update = false
107
+ @user_data = {}
108
+ end
109
+
110
+ def needs_update=(value)
111
+ @version += 1 if value
112
+ @needs_update = value
113
+ end
114
+
115
+ def update_matrix
116
+ @matrix.set_uv_transform(
117
+ @offset.x, @offset.y,
118
+ @repeat.x, @repeat.y,
119
+ @rotation,
120
+ @center.x, @center.y
121
+ )
122
+ end
123
+
124
+ def clone
125
+ self.class.new.copy(self)
126
+ end
127
+
128
+ def copy(source)
129
+ @name = source.name
130
+ @image = source.image
131
+ @mipmaps = source.mipmaps.dup
132
+
133
+ @mapping = source.mapping
134
+ @wrap_s = source.wrap_s
135
+ @wrap_t = source.wrap_t
136
+
137
+ @mag_filter = source.mag_filter
138
+ @min_filter = source.min_filter
139
+
140
+ @anisotropy = source.anisotropy
141
+
142
+ @format = source.format
143
+ @internal_format = source.internal_format
144
+ @type = source.type
145
+
146
+ @offset.copy(source.offset)
147
+ @repeat.copy(source.repeat)
148
+ @center.copy(source.center)
149
+ @rotation = source.rotation
150
+
151
+ @matrix_auto_update = source.matrix_auto_update
152
+ @matrix.copy(source.matrix)
153
+
154
+ @generate_mipmaps = source.generate_mipmaps
155
+ @premultiply_alpha = source.premultiply_alpha
156
+ @flip_y = source.flip_y
157
+ @unpack_alignment = source.unpack_alignment
158
+
159
+ @encoding = source.encoding
160
+ @user_data = source.user_data.dup
161
+
162
+ self
163
+ end
164
+
165
+ def dispose
166
+ @version += 1
167
+ end
168
+
169
+ def to_h
170
+ {
171
+ uuid: @uuid,
172
+ name: @name,
173
+ mapping: @mapping,
174
+ wrap_s: @wrap_s,
175
+ wrap_t: @wrap_t,
176
+ mag_filter: @mag_filter,
177
+ min_filter: @min_filter,
178
+ anisotropy: @anisotropy,
179
+ format: @format,
180
+ type: @type,
181
+ offset: @offset.to_a,
182
+ repeat: @repeat.to_a,
183
+ center: @center.to_a,
184
+ rotation: @rotation,
185
+ flip_y: @flip_y,
186
+ encoding: @encoding
187
+ }
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sunrb
4
+ VERSION = "0.1.0"
5
+ end
data/lib/3rb.rb ADDED
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "3rb/version"
4
+
5
+ module Sunrb
6
+ class Error < StandardError; end
7
+ class GLError < Error; end
8
+ class ShaderCompileError < Error; end
9
+ class TextureLoadError < Error; end
10
+ class ModelLoadError < Error; end
11
+ class InvalidArgumentError < Error; end
12
+ end
13
+
14
+ require_relative "3rb/math/math_utils"
15
+ require_relative "3rb/math/vector2"
16
+ require_relative "3rb/math/vector3"
17
+ require_relative "3rb/math/vector4"
18
+ require_relative "3rb/math/matrix3"
19
+ require_relative "3rb/math/matrix4"
20
+ require_relative "3rb/math/quaternion"
21
+ require_relative "3rb/math/euler"
22
+ require_relative "3rb/math/color"
23
+
24
+ require_relative "3rb/core/buffer_attribute"
25
+ require_relative "3rb/core/object3d"
26
+ require_relative "3rb/core/scene"
27
+ require_relative "3rb/core/group"
28
+
29
+ require_relative "3rb/geometries/buffer_geometry"
30
+ require_relative "3rb/geometries/box_geometry"
31
+ require_relative "3rb/geometries/sphere_geometry"
32
+ require_relative "3rb/geometries/plane_geometry"
33
+ require_relative "3rb/geometries/cylinder_geometry"
34
+ require_relative "3rb/geometries/cone_geometry"
35
+ require_relative "3rb/geometries/torus_geometry"
36
+
37
+ require_relative "3rb/materials/material"
38
+ require_relative "3rb/materials/basic_material"
39
+ require_relative "3rb/materials/lambert_material"
40
+ require_relative "3rb/materials/phong_material"
41
+ require_relative "3rb/materials/standard_material"
42
+ require_relative "3rb/materials/shader_material"
43
+
44
+ require_relative "3rb/objects/mesh"
45
+ require_relative "3rb/objects/line"
46
+ require_relative "3rb/objects/points"
47
+
48
+ require_relative "3rb/cameras/camera"
49
+ require_relative "3rb/cameras/perspective_camera"
50
+ require_relative "3rb/cameras/orthographic_camera"
51
+
52
+ require_relative "3rb/lights/light"
53
+ require_relative "3rb/lights/ambient_light"
54
+ require_relative "3rb/lights/directional_light"
55
+ require_relative "3rb/lights/point_light"
56
+ require_relative "3rb/lights/spot_light"
57
+ require_relative "3rb/lights/hemisphere_light"
58
+ require_relative "3rb/lights/rect_area_light"
59
+
60
+ require_relative "3rb/renderers/renderer"
61
+ require_relative "3rb/renderers/opengl_renderer"
62
+ require_relative "3rb/renderers/shader_lib"
63
+
64
+ require_relative "3rb/dsl/helpers"
65
+ require_relative "3rb/dsl/scene_builder"
66
+
67
+ require_relative "3rb/textures/texture"
68
+ require_relative "3rb/textures/data_texture"
69
+ require_relative "3rb/textures/cube_texture"
70
+ require_relative "3rb/textures/render_target"
71
+
72
+ require_relative "3rb/loaders/loader"
73
+ require_relative "3rb/loaders/texture_loader"
74
+ require_relative "3rb/loaders/obj_loader"
75
+ require_relative "3rb/loaders/gltf_loader"
76
+
77
+ require_relative "3rb/controls/orbit_controls"
78
+
79
+ require_relative "3rb/animation/animation_clip"
80
+ require_relative "3rb/animation/animation_mixer"
81
+
82
+ begin
83
+ require_relative "3rb/native"
84
+ rescue LoadError => e
85
+ warn "Failed to load native FFI bindings: #{e.message}"
86
+ end
@@ -0,0 +1,19 @@
1
+ #version 330 core
2
+
3
+ in vec2 vUv;
4
+ out vec4 FragColor;
5
+
6
+ uniform vec3 diffuse;
7
+ uniform float opacity;
8
+ uniform bool useMap;
9
+ uniform sampler2D map;
10
+
11
+ void main() {
12
+ vec4 diffuseColor = vec4(diffuse, opacity);
13
+
14
+ if (useMap) {
15
+ diffuseColor *= texture(map, vUv);
16
+ }
17
+
18
+ FragColor = diffuseColor;
19
+ }
@@ -0,0 +1,15 @@
1
+ #version 330 core
2
+
3
+ layout (location = 0) in vec3 position;
4
+ layout (location = 1) in vec3 normal;
5
+ layout (location = 2) in vec2 uv;
6
+
7
+ uniform mat4 modelViewMatrix;
8
+ uniform mat4 projectionMatrix;
9
+
10
+ out vec2 vUv;
11
+
12
+ void main() {
13
+ vUv = uv;
14
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
15
+ }
@@ -0,0 +1,53 @@
1
+ // Light structures and uniforms
2
+
3
+ struct AmbientLight {
4
+ vec3 color;
5
+ };
6
+
7
+ struct DirectionalLight {
8
+ vec3 direction;
9
+ vec3 color;
10
+ };
11
+
12
+ struct PointLight {
13
+ vec3 position;
14
+ vec3 color;
15
+ float distance;
16
+ float decay;
17
+ };
18
+
19
+ struct SpotLight {
20
+ vec3 position;
21
+ vec3 direction;
22
+ vec3 color;
23
+ float distance;
24
+ float decay;
25
+ float coneCos;
26
+ float penumbraCos;
27
+ };
28
+
29
+ #define MAX_LIGHTS 4
30
+
31
+ uniform AmbientLight ambientLights[MAX_LIGHTS];
32
+ uniform int numAmbientLights;
33
+
34
+ uniform DirectionalLight directionalLights[MAX_LIGHTS];
35
+ uniform int numDirectionalLights;
36
+
37
+ uniform PointLight pointLights[MAX_LIGHTS];
38
+ uniform int numPointLights;
39
+
40
+ uniform SpotLight spotLights[MAX_LIGHTS];
41
+ uniform int numSpotLights;
42
+
43
+ // Light calculation functions
44
+ float getDistanceAttenuation(float lightDistance, float cutoffDistance, float decayExponent) {
45
+ if (cutoffDistance > 0.0 && decayExponent > 0.0) {
46
+ return pow(clamp(1.0 - pow(lightDistance / cutoffDistance, 4.0), 0.0, 1.0), decayExponent);
47
+ }
48
+ return 1.0;
49
+ }
50
+
51
+ float getSpotAttenuation(float coneCosine, float penumbraCosine, float angleCosine) {
52
+ return smoothstep(coneCosine, penumbraCosine, angleCosine);
53
+ }
@@ -0,0 +1,9 @@
1
+ // Common uniforms for all shaders
2
+ uniform mat4 modelMatrix;
3
+ uniform mat4 modelViewMatrix;
4
+ uniform mat4 projectionMatrix;
5
+ uniform mat4 viewMatrix;
6
+ uniform mat3 normalMatrix;
7
+ uniform vec3 cameraPosition;
8
+
9
+ uniform float time;
@@ -0,0 +1,37 @@
1
+ #version 330 core
2
+
3
+ in vec3 vNormal;
4
+ in vec3 vWorldPosition;
5
+ in vec2 vUv;
6
+
7
+ out vec4 FragColor;
8
+
9
+ uniform vec3 diffuse;
10
+ uniform vec3 emissive;
11
+ uniform float opacity;
12
+ uniform bool useMap;
13
+ uniform sampler2D map;
14
+
15
+ uniform vec3 ambientLightColor;
16
+ uniform vec3 directionalLightDirection;
17
+ uniform vec3 directionalLightColor;
18
+
19
+ void main() {
20
+ vec3 normal = normalize(vNormal);
21
+
22
+ vec4 diffuseColor = vec4(diffuse, opacity);
23
+ if (useMap) {
24
+ diffuseColor *= texture(map, vUv);
25
+ }
26
+
27
+ // Ambient
28
+ vec3 lighting = ambientLightColor;
29
+
30
+ // Directional light (Lambertian)
31
+ float dotNL = max(dot(normal, directionalLightDirection), 0.0);
32
+ lighting += directionalLightColor * dotNL;
33
+
34
+ vec3 outgoingLight = diffuseColor.rgb * lighting + emissive;
35
+
36
+ FragColor = vec4(outgoingLight, diffuseColor.a);
37
+ }