belts_opengl 0.1.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ea257ecc7aeb9a3ea5635678fb1a49d4988b9461875aeb4224e2c4ed464aea91
4
+ data.tar.gz: 8d79cbab0c5508b3c3958f91f7c12c2c4258e7f6c2401d8f27e5ffdbead5314e
5
+ SHA512:
6
+ metadata.gz: 786cb5ffe3b6fb4bad57d01a5cb47d605d53ee45175e95b2cefae9453ee2c90981a7a0c670e43eba51a4800dd43048286d76282b7d3d5cd88c99827875fbe5c5
7
+ data.tar.gz: b347364f0df7ed3207f5c98c831d4940e8d9bc0280db163b2c6971bf47a905d75e5f43346c99b5c0d22cbf20cacdb3e5a519d3f98f287fa47973abbfb9d5ba2c
@@ -0,0 +1,53 @@
1
+ module BeltsOpengl
2
+ class AssetManager
3
+ def initialize
4
+ @shaders = {}
5
+ @meshes = {}
6
+
7
+ build_default_shader
8
+ build_default_meshes
9
+ end
10
+
11
+ def get_shader(key)
12
+ @shaders[key]
13
+ end
14
+
15
+ def get_mesh(key)
16
+ @meshes[key]
17
+ end
18
+
19
+ def build_default_shader
20
+ vert_shader = GL.CreateShader(GL::VERTEX_SHADER)
21
+ vpath = File.join(BeltsOpengl::root, 'lib/belts_opengl/assets/shaders/base.vert')
22
+ vcontent = [File.read(vpath)].pack('p')
23
+ vsize = [File.size(vpath)].pack('I')
24
+ GL.ShaderSource(vert_shader, 1, vcontent, vsize)
25
+ GL.CompileShader(vert_shader)
26
+
27
+ frag_shader = GL.CreateShader(GL::FRAGMENT_SHADER)
28
+ fpath = File.join(BeltsOpengl::root, 'lib/belts_opengl/assets/shaders/base.frag')
29
+ fcontent = [File.read(fpath)].pack('p')
30
+ fsize = [File.size(fpath)].pack('I')
31
+ GL.ShaderSource(frag_shader, 1, fcontent, fsize)
32
+ GL.CompileShader(frag_shader)
33
+
34
+ @shaders[:default] = GL.CreateProgram()
35
+ GL.AttachShader(@shaders[:default], vert_shader)
36
+ GL.AttachShader(@shaders[:default], frag_shader)
37
+ GL.LinkProgram(@shaders[:default])
38
+
39
+ GL.DeleteShader(vert_shader)
40
+ GL.DeleteShader(frag_shader)
41
+ end
42
+
43
+ def build_default_meshes
44
+ default_meshes = {
45
+ square: Assets::Meshes::Square.new,
46
+ triangle: Assets::Meshes::Triangle.new,
47
+ cube: Assets::Meshes::Cube.new
48
+ }
49
+
50
+ @meshes.merge!(default_meshes)
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,69 @@
1
+ module BeltsOpengl::Assets
2
+ module BufferHelpers
3
+ private
4
+
5
+ def create_buffer
6
+ temp = ' ' * 4
7
+ GL.GenBuffers(1, temp)
8
+ temp.unpack('L')[0]
9
+ end
10
+
11
+ def create_vertex_array_buffer
12
+ temp = ' ' * 4
13
+ GL.GenVertexArrays(1, temp)
14
+ temp.unpack('L')[0]
15
+ end
16
+ end
17
+
18
+ class Mesh
19
+ include BufferHelpers
20
+
21
+ U = 1.0 # Unit size
22
+ HU = U/2 # Half unit size
23
+
24
+ def initialize(vertices, indexes)
25
+ @vertices = vertices
26
+ @indexes = indexes
27
+
28
+ @vao = create_vertex_array_buffer
29
+ @vbo = create_buffer
30
+ @ebo = create_buffer
31
+
32
+ upload_vertice_data
33
+ end
34
+
35
+ def draw
36
+ GL.BindVertexArray(@vao)
37
+ GL.DrawElements(GL::TRIANGLES, @indexes.size, GL::UNSIGNED_INT, 0)
38
+ end
39
+
40
+ def destroy
41
+ GL.DeleteVertexArrays(1, [@vao].pack('L'))
42
+ GL.DeleteBuffers(1, [@vbo].pack('L'))
43
+ GL.DeleteBuffers(1, [@ebo].pack('L'))
44
+ end
45
+
46
+ private
47
+
48
+ def upload_vertice_data
49
+ values_per_vertex = 3
50
+
51
+ GL.BindVertexArray(@vao)
52
+ GL.BindBuffer(GL::ARRAY_BUFFER, @vbo)
53
+
54
+ GL.BufferData(GL::ARRAY_BUFFER, @vertices.size * Fiddle::SIZEOF_FLOAT, @vertices.pack('F*'), GL::STATIC_DRAW)
55
+
56
+ GL.BindBuffer(GL::ELEMENT_ARRAY_BUFFER, @ebo)
57
+ GL.BufferData(GL::ELEMENT_ARRAY_BUFFER, @indexes.size * Fiddle::SIZEOF_INT, @indexes.pack('L*'), GL::STATIC_DRAW)
58
+
59
+ GL.VertexAttribPointer(0, 3, GL::FLOAT, GL::FALSE, 6 * Fiddle::SIZEOF_FLOAT, 0)
60
+ GL.VertexAttribPointer(1, 3, GL::FLOAT, GL::FALSE, 6 * Fiddle::SIZEOF_FLOAT, 3 * Fiddle::SIZEOF_FLOAT)
61
+ GL.EnableVertexAttribArray(0)
62
+ GL.EnableVertexAttribArray(1)
63
+
64
+ GL.BindBuffer(GL::ARRAY_BUFFER, 0)
65
+ GL.BindVertexArray(0)
66
+ GL.BindBuffer(GL::ELEMENT_ARRAY_BUFFER, 0)
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,68 @@
1
+ module BeltsOpengl::Assets
2
+ class Meshes::Cube < Mesh
3
+ def initialize
4
+ common_vertices = [
5
+ # Back face
6
+ [-HU, HU, -HU],
7
+ [-HU, -HU, -HU],
8
+ [HU, -HU, -HU],
9
+ [HU, HU, -HU],
10
+
11
+ # Front face
12
+ [HU, HU, HU],
13
+ [HU, -HU, HU],
14
+ [-HU, -HU, HU],
15
+ [-HU, HU, HU]
16
+ ]
17
+
18
+ vertices = [
19
+ # Back face
20
+ *common_vertices[0], *Vec3.back,
21
+ *common_vertices[1], *Vec3.back,
22
+ *common_vertices[2], *Vec3.back,
23
+ *common_vertices[3], *Vec3.back,
24
+
25
+ # Right face
26
+ *common_vertices[3], *Vec3.right,
27
+ *common_vertices[2], *Vec3.right,
28
+ *common_vertices[5], *Vec3.right,
29
+ *common_vertices[4], *Vec3.right,
30
+
31
+ # Front face
32
+ *common_vertices[4], *Vec3.forward,
33
+ *common_vertices[5], *Vec3.forward,
34
+ *common_vertices[6], *Vec3.forward,
35
+ *common_vertices[7], *Vec3.forward,
36
+
37
+ # Left face
38
+ *common_vertices[7], *Vec3.left,
39
+ *common_vertices[6], *Vec3.left,
40
+ *common_vertices[1], *Vec3.left,
41
+ *common_vertices[0], *Vec3.left,
42
+
43
+ # Top face
44
+ *common_vertices[7], *Vec3.up,
45
+ *common_vertices[0], *Vec3.up,
46
+ *common_vertices[3], *Vec3.up,
47
+ *common_vertices[4], *Vec3.up,
48
+
49
+ # Bottom face
50
+ *common_vertices[1], *Vec3.down,
51
+ *common_vertices[6], *Vec3.down,
52
+ *common_vertices[5], *Vec3.down,
53
+ *common_vertices[2], *Vec3.down
54
+ ]
55
+
56
+ indexes = (0..5).map do |i|
57
+ stride = i * 4
58
+
59
+ [
60
+ stride, stride + 1, stride + 2,
61
+ stride + 2, stride + 3, stride
62
+ ]
63
+ end.flatten
64
+
65
+ super(vertices, indexes)
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,18 @@
1
+ module BeltsOpengl::Assets
2
+ class Meshes::Square < Mesh
3
+ def initialize
4
+ vertices = [
5
+ -HU, HU, 0, *Vec3.back,
6
+ -HU, -HU, 0, *Vec3.back,
7
+ HU, -HU, 0, *Vec3.back,
8
+ HU, HU, 0, *Vec3.back
9
+ ]
10
+
11
+ indexes = [
12
+ 0, 1, 2, 2, 3, 0
13
+ ]
14
+
15
+ super(vertices, indexes)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ module BeltsOpengl::Assets
2
+ class Meshes::Triangle < Mesh
3
+ def initialize
4
+ vertices = [
5
+ 0, HU, 0,
6
+ -HU, -HU, 0,
7
+ HU, -HU, 0
8
+ ]
9
+
10
+ indexes = [
11
+ 0, 1, 2
12
+ ]
13
+
14
+ super(vertices, indexes)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ #version 330 core
2
+ out vec4 FragColor;
3
+
4
+ in vec3 normal;
5
+ in vec4 curPosition;
6
+
7
+ void main() {
8
+ float ambient = 0.2;
9
+ vec3 lightPosition = vec3(0, 0, -1);
10
+ vec3 lightDirection = normalize(lightPosition - vec3(curPosition));
11
+
12
+ float diffuse = max(dot(normal, lightDirection), 0.0);
13
+ vec4 objColor = vec4(1.0, 0.5, 1, 1);
14
+ vec4 lightColor = vec4(1, 1, 1, 1);
15
+
16
+ FragColor = objColor * lightColor * (diffuse + ambient);
17
+ }
@@ -0,0 +1,17 @@
1
+ #version 330 core
2
+ layout (location = 0) in vec3 aPosition;
3
+ layout (location = 1) in vec3 aNormal;
4
+
5
+ uniform mat4 camera_matrix;
6
+ uniform mat4 model_matrix;
7
+ uniform mat4 normal_matrix;
8
+
9
+ out vec3 normal;
10
+ out vec4 curPosition;
11
+
12
+ void main() {
13
+ normal = mat3(normal_matrix) * aNormal;
14
+ curPosition = model_matrix * vec4(aPosition, 1.0);
15
+
16
+ gl_Position = camera_matrix * curPosition;
17
+ }
@@ -0,0 +1,4 @@
1
+ CameraData = Struct.new(:projection_type) do
2
+ def perspective? = projection_type == :perspective
3
+ def orthographic? = projection_type == :orthographic
4
+ end
@@ -0,0 +1,5 @@
1
+ LightData = Struct.new(:light_type) do
2
+ def directional? = light_type == :directional
3
+ def point? = light_type == :point
4
+ def ambient? = light_type == :ambient
5
+ end
@@ -0,0 +1 @@
1
+ RenderData = Struct.new(:type, :color)
@@ -0,0 +1,65 @@
1
+ module BeltsOpengl
2
+ class InputManager
3
+ KEY_MAP = {
4
+ GLFW::KEY_W => :w,
5
+ GLFW::KEY_A => :a,
6
+ GLFW::KEY_S => :s,
7
+ GLFW::KEY_D => :d,
8
+ }
9
+
10
+ BUTTON_MAP = {
11
+ GLFW::MOUSE_BUTTON_1 => :mouse_1,
12
+ GLFW::MOUSE_BUTTON_2 => :mouse_2,
13
+ GLFW::MOUSE_BUTTON_3 => :mouse_3
14
+ }
15
+
16
+ def initialize(game, window)
17
+ @game = game
18
+ @window = window
19
+ @input_changes = {}
20
+
21
+ GLFW.SetKeyCallback(@window, key_callback)
22
+ GLFW.SetCursorPosCallback(@window, cursor_callback)
23
+ GLFW.SetMouseButtonCallback(@window, mouse_button_callback)
24
+ end
25
+
26
+ def update
27
+ @game.input.update(@input_changes)
28
+ @input_changes = {}
29
+ end
30
+
31
+ private
32
+
33
+ # NOTE: registering the callback with memoization because the gem has an
34
+ # issue keeping reference to a local variable or method call, resulting
35
+ # in a segfault
36
+ def key_callback
37
+ @_key_callback ||= GLFW::create_callback(:GLFWkeyfun) do |window, key, scancode, action, mods|
38
+ key = KEY_MAP[key]
39
+
40
+ next if key.nil?
41
+ next if action == GLFW::REPEAT
42
+
43
+ @input_changes[key] = action == GLFW::PRESS
44
+ end
45
+ end
46
+
47
+ def cursor_callback
48
+ @_cursor_callback ||= GLFW::create_callback(:GLFWcursorposfun) do |window, x, y|
49
+ @input_changes[:mouse_x] = x
50
+ @input_changes[:mouse_y] = y
51
+ end
52
+ end
53
+
54
+ def mouse_button_callback
55
+ @_mouse_button_callback ||= GLFW::create_callback(:GLFWmousebuttonfun) do |window, button, action, mods|
56
+ button = BUTTON_MAP[button]
57
+
58
+ next if button.nil?
59
+ next if action == GLFW::REPEAT
60
+
61
+ @input_changes[button] = action == GLFW::PRESS
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,17 @@
1
+ module BeltsOpengl
2
+ module Prefab
3
+ module RendererMixin
4
+ class << self
5
+ def included(base)
6
+ base.extend ClassMethods
7
+ end
8
+ end
9
+
10
+ module ClassMethods
11
+ def renderer(type, **options)
12
+ set_component(:render_data, RenderData.new(type, options[:color]))
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,60 @@
1
+ module BeltsOpengl
2
+ class RenderSystem < BeltsEngine::System
3
+ collection :cameras,
4
+ with: [:transform, :camera_data]
5
+
6
+ collection :objects,
7
+ with: [:transform, :render_data]
8
+
9
+ def start
10
+ GL.Enable(GL::DEPTH_TEST)
11
+ GL.Enable(GL::CULL_FACE)
12
+ end
13
+
14
+ def update
15
+ GL.ClearColor(0.07, 0.13, 0.17, 1.0)
16
+ GL.Clear(GL::COLOR_BUFFER_BIT | GL::DEPTH_BUFFER_BIT)
17
+ GL.UseProgram(default_shader)
18
+
19
+ render_entities
20
+ end
21
+
22
+ private
23
+
24
+ def render_entities
25
+ camera_matrix = nil
26
+
27
+ cameras.each_with_components do |transform:, camera_data:, **|
28
+ # view_matrix = Mat4.look_at(transform.position, transform.position + transform.forward, transform.up)
29
+ view_matrix = Mat4.rotation(*-transform.rotation) * Mat4.scale(1, 1, -1) * Mat4.translation(*-transform.position)
30
+ proj_matrix = Mat4.perspective(45, @game.window.ratio, 0.1, 100)
31
+
32
+ ortho_size = 5
33
+ orth_matrix = Mat4.orthographic(-ortho_size * @game.window.ratio, ortho_size * @game.window.ratio, -ortho_size, ortho_size, 0, 10)
34
+
35
+ camera_matrix = (proj_matrix * view_matrix)
36
+ end
37
+
38
+ objects.each_with_components do |transform:, render_data:, **|
39
+ model_matrix = transform.to_matrix
40
+ normal_matrix = model_matrix.inverse.transpose
41
+
42
+ cameraLoc = GL.GetUniformLocation(default_shader, "camera_matrix")
43
+ GL.UniformMatrix4fv(cameraLoc, 1, GL::FALSE, camera_matrix.transpose.to_a.flatten.pack("F*"))
44
+
45
+ modelLoc = GL.GetUniformLocation(default_shader, "model_matrix")
46
+ GL.UniformMatrix4fv(modelLoc, 1, GL::FALSE, model_matrix.transpose.to_a.flatten.pack("F*"))
47
+
48
+ normalLoc = GL.GetUniformLocation(default_shader, "normal_matrix")
49
+ GL.UniformMatrix4fv(normalLoc, 1, GL::FALSE, normal_matrix.transpose.to_a.flatten.pack("F*"))
50
+
51
+ mesh = @game.asset_manager.get_mesh(render_data.type)
52
+ mesh.draw
53
+ end
54
+ end
55
+
56
+ def default_shader
57
+ @game.asset_manager.get_shader(:default)
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,34 @@
1
+ module BeltsOpengl
2
+ class WindowSystem < BeltsEngine::System
3
+ def start
4
+ GLFW.WindowHint(GLFW::ALPHA_BITS, 0)
5
+ @window = GLFW.CreateWindow(640, 480, "Belts Demo", nil, nil)
6
+ GLFW.MakeContextCurrent(@window)
7
+
8
+ @input_manager = BeltsOpengl::InputManager.new(@game, @window)
9
+ end
10
+
11
+ def update
12
+ update_window_size
13
+
14
+ GLFW.SwapBuffers(@window)
15
+ GLFW.PollEvents()
16
+
17
+ @input_manager.update
18
+ end
19
+
20
+ private
21
+
22
+ def update_window_size
23
+ width_ptr = ' ' * 8
24
+ height_ptr = ' ' * 8
25
+ GLFW.GetFramebufferSize(@window, width_ptr, height_ptr)
26
+
27
+ width = width_ptr.unpack('L')[0]
28
+ height = height_ptr.unpack('L')[0]
29
+ GL.Viewport(0, 0, width, height)
30
+
31
+ @game.window.resize(width, height)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ require 'belts_engine'
2
+ require 'opengl'
3
+ require 'glfw'
4
+
5
+ loader = Zeitwerk::Loader.for_gem
6
+ loader.setup
7
+
8
+ module BeltsOpengl
9
+ extend BeltsSupport::Extension
10
+
11
+ def self.install(game)
12
+ require 'belts_opengl/components/camera_data'
13
+ require 'belts_opengl/components/light_data'
14
+ require 'belts_opengl/components/render_data'
15
+
16
+ require 'belts_opengl/systems/window_system'
17
+ require 'belts_opengl/systems/render_system'
18
+
19
+ GLFW.load_lib
20
+ GLFW.Init
21
+ GL.load_lib
22
+
23
+ game.systems.register_system(BeltsOpengl::WindowSystem)
24
+ game.systems.register_system(BeltsOpengl::RenderSystem)
25
+
26
+ game.register_tool(:asset_manager, BeltsOpengl::AssetManager.new)
27
+
28
+ BeltsEngine::Prefab.include BeltsOpengl::Prefab::RendererMixin
29
+ end
30
+
31
+ def self.root
32
+ File.dirname __dir__
33
+ end
34
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: belts_opengl
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Guilherme Graca
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-06-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: belts_engine
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.1.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.1.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: opengl-bindings2
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.0.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 2.0.0
41
+ description:
42
+ email:
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - lib/belts_opengl.rb
48
+ - lib/belts_opengl/asset_manager.rb
49
+ - lib/belts_opengl/assets/mesh.rb
50
+ - lib/belts_opengl/assets/meshes/cube.rb
51
+ - lib/belts_opengl/assets/meshes/square.rb
52
+ - lib/belts_opengl/assets/meshes/triangle.rb
53
+ - lib/belts_opengl/assets/shaders/base.frag
54
+ - lib/belts_opengl/assets/shaders/base.vert
55
+ - lib/belts_opengl/components/camera_data.rb
56
+ - lib/belts_opengl/components/light_data.rb
57
+ - lib/belts_opengl/components/render_data.rb
58
+ - lib/belts_opengl/input_manager.rb
59
+ - lib/belts_opengl/prefab/renderer_mixin.rb
60
+ - lib/belts_opengl/systems/render_system.rb
61
+ - lib/belts_opengl/systems/window_system.rb
62
+ homepage: https://github.com/ggraca/belts
63
+ licenses:
64
+ - MIT
65
+ metadata: {}
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 3.1.2
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubygems_version: 3.3.7
82
+ signing_key:
83
+ specification_version: 4
84
+ summary: OpenGL graphics plugin for the Belts game engine
85
+ test_files: []