mittsu-opengl 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +18 -0
- data/.github/workflows/build-workflow.yml +67 -0
- data/.gitignore +12 -0
- data/.rubocop.yml +1158 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +21 -0
- data/README.md +195 -0
- data/Rakefile +8 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/install-glfw.ps1 +13 -0
- data/lib/mittsu/generic_lib.rb +116 -0
- data/lib/mittsu/glfw/lib.rb +58 -0
- data/lib/mittsu/glfw/window.rb +231 -0
- data/lib/mittsu/opengl/buffer.rb +13 -0
- data/lib/mittsu/opengl/default_target.rb +50 -0
- data/lib/mittsu/opengl/geometry_group.rb +758 -0
- data/lib/mittsu/opengl/geometry_like.rb +132 -0
- data/lib/mittsu/opengl/gl_debug.rb +85 -0
- data/lib/mittsu/opengl/gl_extensions.rb +42 -0
- data/lib/mittsu/opengl/gl_mittsu_params.rb +53 -0
- data/lib/mittsu/opengl/helper.rb +120 -0
- data/lib/mittsu/opengl/implementation.rb +31 -0
- data/lib/mittsu/opengl/lib.rb +19 -0
- data/lib/mittsu/opengl/light_renderer.rb +43 -0
- data/lib/mittsu/opengl/material_basics.rb +57 -0
- data/lib/mittsu/opengl/plugins/shadow_map_plugin.rb +416 -0
- data/lib/mittsu/opengl/plugins/sprite_fragment.glsl +38 -0
- data/lib/mittsu/opengl/plugins/sprite_plugin.rb +250 -0
- data/lib/mittsu/opengl/plugins/sprite_vertex.glsl +31 -0
- data/lib/mittsu/opengl/program.rb +250 -0
- data/lib/mittsu/opengl/renderer.rb +1028 -0
- data/lib/mittsu/opengl/shader/chunk.rb +11 -0
- data/lib/mittsu/opengl/shader/chunks/alphamap_fragment.glsl +5 -0
- data/lib/mittsu/opengl/shader/chunks/alphamap_pars_fragment.glsl +5 -0
- data/lib/mittsu/opengl/shader/chunks/alphatest_fragment.glsl +5 -0
- data/lib/mittsu/opengl/shader/chunks/bumpmap_pars_fragment.glsl +40 -0
- data/lib/mittsu/opengl/shader/chunks/color_fragment.glsl +5 -0
- data/lib/mittsu/opengl/shader/chunks/color_pars_fragment.glsl +5 -0
- data/lib/mittsu/opengl/shader/chunks/color_pars_vertex.glsl +5 -0
- data/lib/mittsu/opengl/shader/chunks/color_vertex.glsl +5 -0
- data/lib/mittsu/opengl/shader/chunks/common.glsl +60 -0
- data/lib/mittsu/opengl/shader/chunks/default_vertex.glsl +15 -0
- data/lib/mittsu/opengl/shader/chunks/defaultnormal_vertex.glsl +21 -0
- data/lib/mittsu/opengl/shader/chunks/envmap_fragment.glsl +62 -0
- data/lib/mittsu/opengl/shader/chunks/envmap_pars_fragment.glsl +21 -0
- data/lib/mittsu/opengl/shader/chunks/envmap_pars_vertex.glsl +7 -0
- data/lib/mittsu/opengl/shader/chunks/envmap_vertex.glsl +17 -0
- data/lib/mittsu/opengl/shader/chunks/fog_fragment.glsl +26 -0
- data/lib/mittsu/opengl/shader/chunks/fog_pars_fragment.glsl +15 -0
- data/lib/mittsu/opengl/shader/chunks/lightmap_fragment.glsl +5 -0
- data/lib/mittsu/opengl/shader/chunks/lightmap_pars_fragment.glsl +6 -0
- data/lib/mittsu/opengl/shader/chunks/lightmap_pars_vertex.glsl +5 -0
- data/lib/mittsu/opengl/shader/chunks/lightmap_vertex.glsl +5 -0
- data/lib/mittsu/opengl/shader/chunks/lights_lambert_pars_vertex.glsl +43 -0
- data/lib/mittsu/opengl/shader/chunks/lights_lambert_vertex.glsl +196 -0
- data/lib/mittsu/opengl/shader/chunks/lights_phong_fragment.glsl +243 -0
- data/lib/mittsu/opengl/shader/chunks/lights_phong_pars_fragment.glsl +58 -0
- data/lib/mittsu/opengl/shader/chunks/lights_phong_pars_vertex.glsl +5 -0
- data/lib/mittsu/opengl/shader/chunks/lights_phong_vertex.glsl +5 -0
- data/lib/mittsu/opengl/shader/chunks/linear_to_gamma_fragment.glsl +2 -0
- data/lib/mittsu/opengl/shader/chunks/logdepthbuf_fragment.glsl +5 -0
- data/lib/mittsu/opengl/shader/chunks/logdepthbuf_pars_fragment.glsl +12 -0
- data/lib/mittsu/opengl/shader/chunks/logdepthbuf_pars_vertex.glsl +11 -0
- data/lib/mittsu/opengl/shader/chunks/logdepthbuf_vertex.glsl +15 -0
- data/lib/mittsu/opengl/shader/chunks/map_fragment.glsl +9 -0
- data/lib/mittsu/opengl/shader/chunks/map_pars_fragment.glsl +11 -0
- data/lib/mittsu/opengl/shader/chunks/map_pars_vertex.glsl +6 -0
- data/lib/mittsu/opengl/shader/chunks/map_particle_fragment.glsl +5 -0
- data/lib/mittsu/opengl/shader/chunks/map_particle_pars_fragment.glsl +6 -0
- data/lib/mittsu/opengl/shader/chunks/map_vertex.glsl +5 -0
- data/lib/mittsu/opengl/shader/chunks/morphnormal_vertex.glsl +12 -0
- data/lib/mittsu/opengl/shader/chunks/morphtarget_pars_vertex.glsl +13 -0
- data/lib/mittsu/opengl/shader/chunks/morphtarget_vertex.glsl +20 -0
- data/lib/mittsu/opengl/shader/chunks/normalmap_pars_fragment.glsl +27 -0
- data/lib/mittsu/opengl/shader/chunks/shadowmap_fragment.glsl +216 -0
- data/lib/mittsu/opengl/shader/chunks/shadowmap_pars_fragment.glsl +19 -0
- data/lib/mittsu/opengl/shader/chunks/shadowmap_pars_vertex.glsl +6 -0
- data/lib/mittsu/opengl/shader/chunks/shadowmap_vertex.glsl +9 -0
- data/lib/mittsu/opengl/shader/chunks/skinbase_vertex.glsl +8 -0
- data/lib/mittsu/opengl/shader/chunks/skinning_pars_vertex.glsl +47 -0
- data/lib/mittsu/opengl/shader/chunks/skinning_vertex.glsl +20 -0
- data/lib/mittsu/opengl/shader/chunks/skinnormal_vertex.glsl +20 -0
- data/lib/mittsu/opengl/shader/chunks/specularmap_fragment.glsl +12 -0
- data/lib/mittsu/opengl/shader/chunks/specularmap_pars_fragment.glsl +5 -0
- data/lib/mittsu/opengl/shader/chunks/worldpos_vertex.glsl +17 -0
- data/lib/mittsu/opengl/shader/lib/basic/basic_fragment.rbsl +37 -0
- data/lib/mittsu/opengl/shader/lib/basic/basic_uniforms.rbslu +3 -0
- data/lib/mittsu/opengl/shader/lib/basic/basic_vertex.rbsl +33 -0
- data/lib/mittsu/opengl/shader/lib/cube/cube_fragment.rbsl +12 -0
- data/lib/mittsu/opengl/shader/lib/cube/cube_uniforms.rbslu +2 -0
- data/lib/mittsu/opengl/shader/lib/cube/cube_vertex.rbsl +12 -0
- data/lib/mittsu/opengl/shader/lib/depth_rgba/depth_rgba_fragment.rbsl +26 -0
- data/lib/mittsu/opengl/shader/lib/depth_rgba/depth_rgba_uniforms.rbslu +0 -0
- data/lib/mittsu/opengl/shader/lib/depth_rgba/depth_rgba_vertex.rbsl +12 -0
- data/lib/mittsu/opengl/shader/lib/lambert/lambert_fragment.rbsl +56 -0
- data/lib/mittsu/opengl/shader/lib/lambert/lambert_uniforms.rbslu +7 -0
- data/lib/mittsu/opengl/shader/lib/lambert/lambert_vertex.rbsl +37 -0
- data/lib/mittsu/opengl/shader/lib/particle_basic/particle_basic_fragment.rbsl +27 -0
- data/lib/mittsu/opengl/shader/lib/particle_basic/particle_basic_uniforms.rbslu +2 -0
- data/lib/mittsu/opengl/shader/lib/particle_basic/particle_basic_vertex.rbsl +25 -0
- data/lib/mittsu/opengl/shader/lib/phong/phong_fragment.rbsl +45 -0
- data/lib/mittsu/opengl/shader/lib/phong/phong_uniforms.rbslu +11 -0
- data/lib/mittsu/opengl/shader/lib/phong/phong_vertex.rbsl +43 -0
- data/lib/mittsu/opengl/shader/lib.rb +45 -0
- data/lib/mittsu/opengl/shader/rbsl_loader.rb +168 -0
- data/lib/mittsu/opengl/shader/templates/fragment.glsl.erb +105 -0
- data/lib/mittsu/opengl/shader/templates/vertex.glsl.erb +143 -0
- data/lib/mittsu/opengl/shader/uniforms_lib.rb +86 -0
- data/lib/mittsu/opengl/shader/uniforms_utils.rb +31 -0
- data/lib/mittsu/opengl/shader.rb +56 -0
- data/lib/mittsu/opengl/state.rb +205 -0
- data/lib/mittsu/opengl/version.rb +5 -0
- data/lib/mittsu/opengl.rb +2 -0
- data/lib/mittsu/opengl_implementation/core/buffer_geometry.rb +11 -0
- data/lib/mittsu/opengl_implementation/core/geometry.rb +346 -0
- data/lib/mittsu/opengl_implementation/core/object_3d.rb +134 -0
- data/lib/mittsu/opengl_implementation/lights/ambient_light.rb +26 -0
- data/lib/mittsu/opengl_implementation/lights/directional_light.rb +35 -0
- data/lib/mittsu/opengl_implementation/lights/hemisphere_light.rb +39 -0
- data/lib/mittsu/opengl_implementation/lights/light.rb +55 -0
- data/lib/mittsu/opengl_implementation/lights/point_light.rb +36 -0
- data/lib/mittsu/opengl_implementation/lights/spot_light.rb +47 -0
- data/lib/mittsu/opengl_implementation/materials/line_basic_material.rb +16 -0
- data/lib/mittsu/opengl_implementation/materials/material.rb +274 -0
- data/lib/mittsu/opengl_implementation/materials/mesh_basic_material.rb +21 -0
- data/lib/mittsu/opengl_implementation/materials/mesh_lambert_material.rb +33 -0
- data/lib/mittsu/opengl_implementation/materials/mesh_phong_material.rb +44 -0
- data/lib/mittsu/opengl_implementation/materials/point_cloud_material.rb +27 -0
- data/lib/mittsu/opengl_implementation/materials/shader_material.rb +11 -0
- data/lib/mittsu/opengl_implementation/objects/group.rb +9 -0
- data/lib/mittsu/opengl_implementation/objects/line.rb +45 -0
- data/lib/mittsu/opengl_implementation/objects/mesh.rb +70 -0
- data/lib/mittsu/opengl_implementation/objects/point_cloud.rb +39 -0
- data/lib/mittsu/opengl_implementation/objects/sprite.rb +12 -0
- data/lib/mittsu/opengl_implementation/scenes/scene.rb +9 -0
- data/lib/mittsu/opengl_implementation/textures/compressed_texture.rb +20 -0
- data/lib/mittsu/opengl_implementation/textures/cube_texture.rb +77 -0
- data/lib/mittsu/opengl_implementation/textures/data_texture.rb +21 -0
- data/lib/mittsu/opengl_implementation/textures/render_target.rb +124 -0
- data/lib/mittsu/opengl_implementation/textures/texture.rb +107 -0
- data/mittsu-opengl.gemspec +36 -0
- metadata +314 -0
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
4
|
+
|
5
|
+
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
|
6
|
+
|
7
|
+
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
8
|
+
|
9
|
+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
|
10
|
+
|
11
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
12
|
+
|
13
|
+
This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015-2022 Danielle Smith
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,195 @@
|
|
1
|
+
# Mittsu
|
2
|
+
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/mittsu-opengl.svg)](https://badge.fury.io/rb/mittsu-opengl)
|
4
|
+
[![Test Coverage](https://api.codeclimate.com/v1/badges/XXX/test_coverage)](https://codeclimate.com/github/danini-the-panini/mittsu-opengl/test_coverage)
|
5
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/XXX/maintainability)](https://codeclimate.com/github/danini-the-panini/mittsu-opengl/maintainability)
|
6
|
+
[![Build Status](https://github.com/danini-the-panini/mittsu-opengl/workflows/Build/badge.svg)](https://github.com/danini-the-panini/mittsu-opengl/actions?query=workflow%3A%22Build%22)
|
7
|
+
|
8
|
+
OpenGL renderer for Mittsu
|
9
|
+
|
10
|
+
OpenGL 3 renderer for Mittsu using GLFW for context creation.
|
11
|
+
|
12
|
+
## GIFs!
|
13
|
+
|
14
|
+
![Normal-mapped Earth](https://cloud.githubusercontent.com/assets/1171825/18411863/45328540-7781-11e6-986b-6e3f2551c719.gif)
|
15
|
+
![Point Light](https://cloud.githubusercontent.com/assets/1171825/18411861/4531bb4c-7781-11e6-92b4-b6ebda60e2c9.gif)
|
16
|
+
![Tank Demo](https://cloud.githubusercontent.com/assets/1171825/18411862/4531fe9a-7781-11e6-9665-b172df1a3645.gif)
|
17
|
+
|
18
|
+
(You can find the source for the Tank Demo [here](https://github.com/danini-the-panini/mittsu-tank-demo))
|
19
|
+
|
20
|
+
## Installation
|
21
|
+
|
22
|
+
Install the prerequisites:
|
23
|
+
|
24
|
+
Mittsu depends on Ruby 2.6+, OpenGL 3.3+, and GLFW 3.1+
|
25
|
+
|
26
|
+
```bash
|
27
|
+
# OSX
|
28
|
+
$ brew install glfw3
|
29
|
+
|
30
|
+
# Ubuntu
|
31
|
+
$ sudo apt install libglfw3
|
32
|
+
|
33
|
+
# Fedora
|
34
|
+
$ sudo dnf install glfw
|
35
|
+
```
|
36
|
+
|
37
|
+
**NOTE:** On Windows, you will have to manually specify the glfw3.dll path in an environment variable
|
38
|
+
(you can download it [here](http://www.glfw.org/download.html))
|
39
|
+
```bash
|
40
|
+
# ex) set MITTSU_LIBGLFW_PATH=C:\Users\username\lib-mingw-w64
|
41
|
+
> set MITTSU_LIBGLFW_PATH=C:\path\to\glfw3.dll
|
42
|
+
> ruby your_awesome_mittsu_app.rb
|
43
|
+
```
|
44
|
+
|
45
|
+
Add this line to your application's Gemfile:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
gem 'mittsu-opengl'
|
49
|
+
```
|
50
|
+
|
51
|
+
And then execute:
|
52
|
+
|
53
|
+
$ bundle
|
54
|
+
|
55
|
+
Or install it yourself as:
|
56
|
+
|
57
|
+
$ gem install mittsu-opengl
|
58
|
+
|
59
|
+
## Usage
|
60
|
+
|
61
|
+
### tl;dr
|
62
|
+
|
63
|
+
Copy-Paste and Run:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
require 'mittsu-opengl'
|
67
|
+
|
68
|
+
SCREEN_WIDTH = 800
|
69
|
+
SCREEN_HEIGHT = 600
|
70
|
+
ASPECT = SCREEN_WIDTH.to_f / SCREEN_HEIGHT.to_f
|
71
|
+
|
72
|
+
renderer = Mittsu::OpenGL::Renderer.new width: SCREEN_WIDTH, height: SCREEN_HEIGHT, title: 'Hello, World!'
|
73
|
+
|
74
|
+
scene = Mittsu::Scene.new
|
75
|
+
|
76
|
+
camera = Mittsu::PerspectiveCamera.new(75.0, ASPECT, 0.1, 1000.0)
|
77
|
+
camera.position.z = 5.0
|
78
|
+
|
79
|
+
box = Mittsu::Mesh.new(
|
80
|
+
Mittsu::BoxGeometry.new(1.0, 1.0, 1.0),
|
81
|
+
Mittsu::MeshBasicMaterial.new(color: 0x00ff00)
|
82
|
+
)
|
83
|
+
|
84
|
+
scene.add(box)
|
85
|
+
|
86
|
+
renderer.window.run do
|
87
|
+
box.rotation.x += 0.1
|
88
|
+
box.rotation.y += 0.1
|
89
|
+
|
90
|
+
renderer.render(scene, camera)
|
91
|
+
end
|
92
|
+
```
|
93
|
+
|
94
|
+
### Step by Step
|
95
|
+
|
96
|
+
First, we need to require the Mittsu OpenGL renderer in order to use it:
|
97
|
+
```ruby
|
98
|
+
require 'mittsu'
|
99
|
+
```
|
100
|
+
|
101
|
+
Then, we'll define some constants to help us with setting up our 3D environment:
|
102
|
+
```ruby
|
103
|
+
SCREEN_WIDTH = 800
|
104
|
+
SCREEN_HEIGHT = 600
|
105
|
+
ASPECT = SCREEN_WIDTH.to_f / SCREEN_HEIGHT.to_f
|
106
|
+
```
|
107
|
+
|
108
|
+
The aspect ratio will be used for setting up the camera later.
|
109
|
+
|
110
|
+
Once we have all that we can create the canvas we will use to draw our graphics onto. In Mittsu this is called a renderer. It provides a window and an OpenGL context:
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
renderer = Mittsu::OpenGL::Renderer.new width: SCREEN_WIDTH, height: SCREEN_HEIGHT, title: 'Hello, World!'
|
114
|
+
```
|
115
|
+
This will give us an 800x600 window with the title `Hello, World!`.
|
116
|
+
|
117
|
+
Now that we have our canvas, let's start setting up the scene we wish to draw onto it:
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
scene = Mittsu::Scene.new
|
121
|
+
```
|
122
|
+
|
123
|
+
A scene is like a stage where all our 3D objects live and animate.
|
124
|
+
|
125
|
+
We can't draw a 3D scene without knowing where we're looking:
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
camera = Mittsu::PerspectiveCamera.new(75.0, ASPECT, 0.1, 1000.0)
|
129
|
+
```
|
130
|
+
|
131
|
+
This camera has a 75° field-of-view (FOV), the aspect ratio of the window (which we defined earlier), and shows everything between a distance of 0.1 to 1000.0 away from the camera.
|
132
|
+
|
133
|
+
The camera starts off at the origin `[0,0,0]` and faces the negative Z-axis. We'll position it somewhere along the positive Z-axis so that it is looking at the center of the scene from a short distance:
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
camera.position.z = 5.0
|
137
|
+
```
|
138
|
+
|
139
|
+
Our scene isn't going to be very exciting if there is nothing in it, so we'll create a box:
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
box = Mittsu::Mesh.new(
|
143
|
+
Mittsu::BoxGeometry.new(1.0, 1.0, 1.0),
|
144
|
+
Mittsu::MeshBasicMaterial.new(color: 0x00ff00)
|
145
|
+
)
|
146
|
+
```
|
147
|
+
|
148
|
+
A `Mesh` in Mittsu is the combination of a `Geometry` (the shape of the object) and a `Material` (the "look" of the object). Here we've created a 1x1x1 box that is colored green.
|
149
|
+
|
150
|
+
Box in hand, we make it part of our scene:
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
scene.add(box)
|
154
|
+
```
|
155
|
+
|
156
|
+
Here comes the fun part... the render loop!
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
renderer.window.run do
|
160
|
+
```
|
161
|
+
|
162
|
+
The given block is called every frame. This is where you can tell the renderer what scene to draw, and do any updates to the objects in your scene.
|
163
|
+
|
164
|
+
Just to make things a bit more interesting, we'll make the box rotate around its X and Y axes, so that it spins like crazy.
|
165
|
+
|
166
|
+
```ruby
|
167
|
+
box.rotation.x += 0.1
|
168
|
+
box.rotation.y += 0.1
|
169
|
+
```
|
170
|
+
|
171
|
+
Last but not least, we tell the renderer to draw our scene this frame, which will tell the graphics processor to draw our green box with its updated rotation.
|
172
|
+
|
173
|
+
```ruby
|
174
|
+
renderer.render(scene, camera)
|
175
|
+
```
|
176
|
+
|
177
|
+
Easy peasy! :)
|
178
|
+
|
179
|
+
```ruby
|
180
|
+
end
|
181
|
+
```
|
182
|
+
|
183
|
+
### More Resources
|
184
|
+
|
185
|
+
If you just want to see what Mittsu can do and how to do it, take a peek inside the `examples` folder.
|
186
|
+
|
187
|
+
## Contributing
|
188
|
+
|
189
|
+
1. Fork it ( https://github.com/danini-the-panini/mittsu-opengl/fork )
|
190
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
191
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
192
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
193
|
+
5. Create a new Pull Request
|
194
|
+
|
195
|
+
Thank you for helping me help you help us all. ;)
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "mittsu"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/install-glfw.ps1
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
$glfwversion="3.3.1"
|
2
|
+
|
3
|
+
Invoke-WebRequest "https://github.com/glfw/glfw/releases/download/$glfwversion/glfw-$glfwversion.bin.WIN32.zip" -OutFile "$pwd\glfw-$glfwversion.bin.WIN32.zip"
|
4
|
+
|
5
|
+
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
6
|
+
function Unzip
|
7
|
+
{
|
8
|
+
param([string]$zipfile, [string]$outpath)
|
9
|
+
|
10
|
+
[System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $outpath)
|
11
|
+
}
|
12
|
+
|
13
|
+
Unzip "$pwd\glfw-$glfwversion.bin.WIN32.zip" "$pwd"
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'opengl'
|
2
|
+
require 'open3'
|
3
|
+
|
4
|
+
module Mittsu
|
5
|
+
module GenericLib
|
6
|
+
def discover
|
7
|
+
case GL.get_platform
|
8
|
+
when :OPENGL_PLATFORM_WINDOWS
|
9
|
+
self::Windows.new
|
10
|
+
when :OPENGL_PLATFORM_MACOSX
|
11
|
+
self::MacOS.new
|
12
|
+
when :OPENGL_PLATFORM_LINUX
|
13
|
+
self::Linux.new
|
14
|
+
else
|
15
|
+
warn "WARNING: Unsupported platform: #{GL.get_platform}"
|
16
|
+
Base.new
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Base
|
21
|
+
def path; nil; end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Linux < Base
|
25
|
+
def path
|
26
|
+
@_path ||= begin
|
27
|
+
ldconfig_lib || driver_specific_lib || sixtyfour_bit_lib || fallback_lib || give_up
|
28
|
+
end.tap do |result|
|
29
|
+
print_debug_info(result) if DEBUG
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class << self
|
34
|
+
def kernel_module_in_use
|
35
|
+
lspci_line, stderr, _status = Open3.capture3("lspci -nnk | grep -i vga -A3 | grep 'in use'")
|
36
|
+
puts stderr if DEBUG
|
37
|
+
/in use:\s*(\S+)/ =~ lspci_line && $1
|
38
|
+
rescue
|
39
|
+
''
|
40
|
+
end
|
41
|
+
|
42
|
+
def lib_paths
|
43
|
+
Dir.glob('/usr/lib*/**/libGL.so*')
|
44
|
+
rescue
|
45
|
+
[]
|
46
|
+
end
|
47
|
+
|
48
|
+
def sixtyfour_bits?
|
49
|
+
1.size == 8
|
50
|
+
end
|
51
|
+
|
52
|
+
def ldconfig
|
53
|
+
`ldconfig -p | grep 'libGL\\.so'`.lines
|
54
|
+
rescue
|
55
|
+
[]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def ldconfig_lib
|
62
|
+
return nil if ldconfig.empty?
|
63
|
+
@_debug = { source: 'ldconfig', info: ldconfig.inspect } if DEBUG
|
64
|
+
ldconfig_for_arch = ldconfig.reject { |lib| @loader.sixtyfour_bits? ^ ldconfig_64?(lib) }
|
65
|
+
ldconfig_for_arch.first.match(/=> (\/.*)$/)[1]
|
66
|
+
end
|
67
|
+
|
68
|
+
def ldconfig_64?(lib)
|
69
|
+
lib =~ /\([^\)]*64[^\)]*\) =>/
|
70
|
+
end
|
71
|
+
|
72
|
+
def driver_specific_lib
|
73
|
+
return nil if libs.empty?
|
74
|
+
@_debug = { source: 'driver', info: kernel_module } if DEBUG
|
75
|
+
libs.select { |lib| lib =~ /nvidia/ }.first if kernel_module =~ /nvidia/
|
76
|
+
end
|
77
|
+
|
78
|
+
def sixtyfour_bit_lib
|
79
|
+
return nil if libs.empty?
|
80
|
+
sixtyfour_bit_libs = libs.select { |lib| lib =~ /64/ }
|
81
|
+
@_debug = { source: '64', info: sixtyfour_bit_libs.inspect } if DEBUG
|
82
|
+
sixtyfour_bit_libs.first if @loader.sixtyfour_bits?
|
83
|
+
end
|
84
|
+
|
85
|
+
def fallback_lib
|
86
|
+
return nil if libs.empty?
|
87
|
+
@_debug = { source: 'fallback', info: libs.inspect } if DEBUG
|
88
|
+
libs.first
|
89
|
+
end
|
90
|
+
|
91
|
+
def give_up
|
92
|
+
@_debug = { source: 'none', info: nil } if DEBUG
|
93
|
+
nil
|
94
|
+
end
|
95
|
+
|
96
|
+
def kernel_module
|
97
|
+
@_kernel_module ||= @loader.kernel_module_in_use
|
98
|
+
end
|
99
|
+
|
100
|
+
def libs
|
101
|
+
@_libs ||= @loader.lib_paths.sort_by(&:length)
|
102
|
+
end
|
103
|
+
|
104
|
+
def ldconfig
|
105
|
+
@_ldconfig ||= @loader.ldconfig
|
106
|
+
end
|
107
|
+
|
108
|
+
def print_debug_info(result)
|
109
|
+
puts "Loading lib path: #{result.inspect}"
|
110
|
+
puts "Source: #{@_debug[:source]}"
|
111
|
+
puts "Info: #{@_debug[:info]}"
|
112
|
+
puts "64-bit? #{@loader.sixtyfour_bits?}"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'mittsu/generic_lib'
|
2
|
+
|
3
|
+
module Mittsu
|
4
|
+
module GLFW
|
5
|
+
module Lib
|
6
|
+
extend GenericLib
|
7
|
+
|
8
|
+
class Linux < GenericLib::Linux
|
9
|
+
def initialize(loader = Linux)
|
10
|
+
@loader = loader
|
11
|
+
end
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def lib_paths
|
15
|
+
Dir.glob('/usr/lib*/**/libglfw*.so*')
|
16
|
+
rescue
|
17
|
+
[]
|
18
|
+
end
|
19
|
+
|
20
|
+
def ldconfig
|
21
|
+
out, stderr, _status = Open3.capture3("ldconfig -p | grep 'libglfw3\\?\\.so'")
|
22
|
+
puts stderr if DEBUG
|
23
|
+
out.lines
|
24
|
+
rescue
|
25
|
+
[]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Windows < GenericLib::Base
|
31
|
+
def path
|
32
|
+
'glfw3.dll'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class MacOS < GenericLib::Base
|
37
|
+
SEARCH_GLOBS = ['/usr/local/lib/**',
|
38
|
+
'/usr/lib/**',
|
39
|
+
'/opt/homebrew/**']
|
40
|
+
|
41
|
+
def path
|
42
|
+
@_path ||= find_match&.to_s
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def find_match
|
48
|
+
SEARCH_GLOBS.each do |glob|
|
49
|
+
matches = Dir.glob("#{glob}/libglfw*.dylib")
|
50
|
+
next if matches.empty?
|
51
|
+
|
52
|
+
return matches.find { |m| m.end_with?('libglfw3.dylib') || m.end_with?('libglfw.3.dylib') } || matches.first
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,231 @@
|
|
1
|
+
require 'opengl'
|
2
|
+
require 'glfw'
|
3
|
+
|
4
|
+
require 'mittsu/utils'
|
5
|
+
require 'mittsu/glfw/lib'
|
6
|
+
glfw_lib = Mittsu::GLFW::Lib.discover
|
7
|
+
::GLFW.load_lib(ENV["MITTSU_LIBGLFW_PATH"] || glfw_lib.path, Mittsu.debug?) unless Mittsu.test?
|
8
|
+
|
9
|
+
module Mittsu
|
10
|
+
module GLFW
|
11
|
+
class Window
|
12
|
+
attr_accessor :key_press_handler, :key_release_handler, :key_repeat_handler, :char_input_handler, :cursor_pos_handler, :mouse_button_press_handler, :mouse_button_release_handler, :scroll_handler, :framebuffer_size_handler
|
13
|
+
|
14
|
+
def initialize(width, height, title, antialias: 0)
|
15
|
+
::GLFW.Init
|
16
|
+
|
17
|
+
::GLFW.WindowHint ::GLFW::OPENGL_PROFILE, ::GLFW::OPENGL_CORE_PROFILE
|
18
|
+
::GLFW.WindowHint ::GLFW::OPENGL_FORWARD_COMPAT, GL::TRUE
|
19
|
+
::GLFW.WindowHint ::GLFW::CONTEXT_VERSION_MAJOR, 3
|
20
|
+
::GLFW.WindowHint ::GLFW::CONTEXT_VERSION_MINOR, 3
|
21
|
+
::GLFW.WindowHint ::GLFW::CONTEXT_REVISION, 0
|
22
|
+
|
23
|
+
if antialias > 0
|
24
|
+
::GLFW.WindowHint ::GLFW::SAMPLES, antialias
|
25
|
+
end
|
26
|
+
|
27
|
+
@width, @height, @title = width, height, title
|
28
|
+
@handle = ::GLFW.CreateWindow(@width, @height, @title, nil, nil)
|
29
|
+
if @handle.null?
|
30
|
+
raise "Unable to create window."
|
31
|
+
end
|
32
|
+
::GLFW.MakeContextCurrent @handle
|
33
|
+
::GLFW.SwapInterval 1
|
34
|
+
|
35
|
+
this = self
|
36
|
+
@key_callback = ::GLFW::create_callback(:GLFWkeyfun) do |window_handle, key, scancode, action, mods|
|
37
|
+
if action == ::GLFW::PRESS
|
38
|
+
this.key_press_handler.call(key) unless this.key_press_handler.nil?
|
39
|
+
this.key_repeat_handler.call(key) unless this.key_repeat_handler.nil?
|
40
|
+
elsif action == ::GLFW::RELEASE
|
41
|
+
this.key_release_handler.call(key) unless this.key_release_handler.nil?
|
42
|
+
elsif action == ::GLFW::REPEAT
|
43
|
+
this.key_repeat_handler.call(key) unless this.key_repeat_handler.nil?
|
44
|
+
end
|
45
|
+
end
|
46
|
+
::GLFW.SetKeyCallback(@handle, @key_callback)
|
47
|
+
|
48
|
+
@char_callback = ::GLFW::create_callback(:GLFWcharfun) do |window_handle, codepoint|
|
49
|
+
char = [codepoint].pack('U')
|
50
|
+
this.char_input_handler.call(char) unless this.char_input_handler.nil?
|
51
|
+
end
|
52
|
+
::GLFW.SetCharCallback(@handle, @char_callback)
|
53
|
+
|
54
|
+
@cursor_pos_callback = ::GLFW::create_callback(:GLFWcursorposfun) do |window_handle, xpos, ypos|
|
55
|
+
this.cursor_pos_handler.call(Vector2.new(xpos, ypos)) unless this.cursor_pos_handler.nil?
|
56
|
+
end
|
57
|
+
::GLFW.SetCursorPosCallback(@handle, @cursor_pos_callback)
|
58
|
+
|
59
|
+
@mouse_button_callback = ::GLFW::create_callback(:GLFWmousebuttonfun) do |window_handle, button, action, mods|
|
60
|
+
mpos = this.mouse_position
|
61
|
+
if action == ::GLFW::PRESS
|
62
|
+
this.mouse_button_press_handler.call(button, mpos) unless this.mouse_button_press_handler.nil?
|
63
|
+
elsif action == ::GLFW::RELEASE
|
64
|
+
this.mouse_button_release_handler.call(button, mpos) unless this.mouse_button_release_handler.nil?
|
65
|
+
end
|
66
|
+
end
|
67
|
+
::GLFW.SetMouseButtonCallback(@handle, @mouse_button_callback)
|
68
|
+
|
69
|
+
@scroll_callback = ::GLFW::create_callback(:GLFWscrollfun) do |window_handle, xoffset, yoffset|
|
70
|
+
this.scroll_handler.call(Vector2.new(xoffset, yoffset)) unless this.scroll_handler.nil?
|
71
|
+
end
|
72
|
+
::GLFW.SetScrollCallback(@handle, @scroll_callback)
|
73
|
+
|
74
|
+
@frabuffer_size_callback = ::GLFW::create_callback(:GLFWframebuffersizefun) do |window_handle, new_width, new_height|
|
75
|
+
this.framebuffer_size_handler.call(new_width, new_height) unless this.framebuffer_size_handler.nil?
|
76
|
+
end
|
77
|
+
::GLFW.SetFramebufferSizeCallback(@handle, @frabuffer_size_callback)
|
78
|
+
|
79
|
+
@joystick_buttons = poll_all_joysticks_buttons
|
80
|
+
end
|
81
|
+
|
82
|
+
def run
|
83
|
+
while ::GLFW.WindowShouldClose(@handle) == 0
|
84
|
+
yield
|
85
|
+
|
86
|
+
::GLFW.SwapBuffers @handle
|
87
|
+
::GLFW.PollEvents
|
88
|
+
poll_joystick_events
|
89
|
+
end
|
90
|
+
::GLFW.DestroyWindow @handle
|
91
|
+
::GLFW.Terminate
|
92
|
+
end
|
93
|
+
|
94
|
+
def framebuffer_size
|
95
|
+
width, height = ' '*8, ' '*8
|
96
|
+
::GLFW.GetFramebufferSize(@handle, width, height)
|
97
|
+
[width.unpack('L')[0], height.unpack('L')[0]]
|
98
|
+
end
|
99
|
+
|
100
|
+
def on_key_pressed &block
|
101
|
+
@key_press_handler = block
|
102
|
+
end
|
103
|
+
|
104
|
+
def on_key_released &block
|
105
|
+
@key_release_handler = block
|
106
|
+
end
|
107
|
+
|
108
|
+
def on_key_typed &block
|
109
|
+
@key_repeat_handler = block
|
110
|
+
end
|
111
|
+
|
112
|
+
def key_down?(key)
|
113
|
+
::GLFW.GetKey(@handle, key) == ::GLFW::PRESS
|
114
|
+
end
|
115
|
+
|
116
|
+
def on_character_input &block
|
117
|
+
@char_input_handler = block
|
118
|
+
end
|
119
|
+
|
120
|
+
def on_mouse_move &block
|
121
|
+
@cursor_pos_handler = block
|
122
|
+
end
|
123
|
+
|
124
|
+
def on_mouse_button_pressed &block
|
125
|
+
@mouse_button_press_handler = block
|
126
|
+
end
|
127
|
+
|
128
|
+
def on_mouse_button_released &block
|
129
|
+
@mouse_button_release_handler = block
|
130
|
+
end
|
131
|
+
|
132
|
+
def mouse_position
|
133
|
+
xpos, ypos = ' '*8, ' '*8
|
134
|
+
::GLFW.GetCursorPos(@handle, xpos, ypos);
|
135
|
+
Vector2.new(xpos.unpack('D')[0], ypos.unpack('D')[0])
|
136
|
+
end
|
137
|
+
|
138
|
+
def mouse_button_down?(button)
|
139
|
+
::GLFW.GetMouseButton(@handle, button) == ::GLFW::PRESS
|
140
|
+
end
|
141
|
+
|
142
|
+
def on_scroll &block
|
143
|
+
@scroll_handler = block
|
144
|
+
end
|
145
|
+
|
146
|
+
def on_resize &block
|
147
|
+
@framebuffer_size_handler = block
|
148
|
+
end
|
149
|
+
|
150
|
+
def joystick_buttons(joystick = ::GLFW::JOYSTICK_1)
|
151
|
+
@joystick_buttons = poll_all_joysticks_buttons
|
152
|
+
@joystick_buttons[joystick]
|
153
|
+
end
|
154
|
+
|
155
|
+
def joystick_axes(joystick = ::GLFW::JOYSTICK_1)
|
156
|
+
return [] unless joystick_present?(joystick)
|
157
|
+
count = ' ' * 4
|
158
|
+
array = ::GLFW.GetJoystickAxes(joystick, count)
|
159
|
+
count = count.unpack('l')[0]
|
160
|
+
array[0, count * 4].unpack('f' * count)
|
161
|
+
end
|
162
|
+
|
163
|
+
def on_joystick_button_pressed &block
|
164
|
+
@joystick_button_press_handler = block
|
165
|
+
end
|
166
|
+
|
167
|
+
def on_joystick_button_released &block
|
168
|
+
@joystick_button_release_handler = block
|
169
|
+
end
|
170
|
+
|
171
|
+
def joystick_present?(joystick = ::GLFW::JOYSTICK_1)
|
172
|
+
::GLFW.JoystickPresent(joystick).nonzero?
|
173
|
+
end
|
174
|
+
|
175
|
+
def joystick_button_down?(button, joystick = ::GLFW::JOYSTICK_1)
|
176
|
+
@joystick_buttons[joystick][button]
|
177
|
+
end
|
178
|
+
|
179
|
+
def joystick_name(joystick = ::GLFW::JOYSTICK_1)
|
180
|
+
::GLFW.GetJoystickName(joystick)
|
181
|
+
end
|
182
|
+
|
183
|
+
def set_mouselock(value)
|
184
|
+
if value
|
185
|
+
::GLFW.SetInputMode(@handle, ::GLFW::CURSOR, ::GLFW::CURSOR_DISABLED)
|
186
|
+
else
|
187
|
+
::GLFW.SetInputMode(@handle, ::GLFW::CURSOR, ::GLFW::CURSOR_NORMAL)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
private
|
192
|
+
|
193
|
+
def poll_all_joysticks_buttons
|
194
|
+
(::GLFW::JOYSTICK_1..::GLFW::JOYSTICK_LAST).map do |joystick|
|
195
|
+
poll_joystick_buttons(joystick)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def poll_joystick_buttons(joystick)
|
200
|
+
return nil unless joystick_present?(joystick)
|
201
|
+
count = ' ' * 4
|
202
|
+
array = ::GLFW.GetJoystickButtons(joystick, count)
|
203
|
+
count = count.unpack('l')[0]
|
204
|
+
array[0, count].unpack('c' * count).map(&:nonzero?)
|
205
|
+
end
|
206
|
+
|
207
|
+
def poll_joystick_events
|
208
|
+
new_joystick_buttons = poll_all_joysticks_buttons
|
209
|
+
new_joystick_buttons.each_with_index do |buttons, joystick|
|
210
|
+
poll_single_joystick_events(joystick, buttons)
|
211
|
+
end
|
212
|
+
@joystick_buttons = new_joystick_buttons
|
213
|
+
end
|
214
|
+
|
215
|
+
def poll_single_joystick_events(joystick, buttons)
|
216
|
+
return if buttons.nil?
|
217
|
+
buttons.each_with_index do |pressed, button|
|
218
|
+
fire_joystick_button_event(joystick, button, pressed)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def fire_joystick_button_event(joystick, button, pressed)
|
223
|
+
if !@joystick_buttons[joystick][button] && pressed
|
224
|
+
@joystick_button_press_handler.call(joystick, button) unless @joystick_button_press_handler.nil?
|
225
|
+
elsif @joystick_buttons[joystick][button] && !pressed
|
226
|
+
@joystick_button_release_handler.call(joystick, button) unless @joystick_button_release_handler.nil?
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|