belts_opengl 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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: []