rbglox 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.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ THE MIT LICENSE
2
+
3
+ Copyright (c) 2011, Mihail Szabolcs
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 all
13
+ 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 THE
21
+ SOFTWARE.
@@ -0,0 +1,184 @@
1
+ rbGLox
2
+ ======
3
+ rbGLox is a small wrapper over the ruby-opengl, ruby-glfw family by abstracting
4
+ and providing some high-level interfaces for things like "Textures",
5
+ "GLSL Shaders", basic "Geometry" and others.
6
+
7
+ It's ideal for rapid prototyping new and interesting ideas.
8
+
9
+ rbGLox is the sister project of [pyGLox](http://github.com/icebreaker/pyGLox).
10
+
11
+ Dependencies
12
+ ------------
13
+ * [ruby-opengl](https://rubygems.org/gems/ruby-opengl)
14
+ * [ruby-glfw](https://rubygems.org/gems/ruby-glfw)
15
+ * [directory-watcher](https://rubygems.org/gems/directory_watcher)
16
+
17
+ Getting Started
18
+ ---------------
19
+
20
+ ### Install
21
+
22
+ gem install rbglox
23
+
24
+ ### Library
25
+
26
+ Using rbGLox as a library is a very easy :)
27
+
28
+ ```ruby
29
+ require 'rbglox'
30
+ class DemoApp < RBGLox::App
31
+ def init
32
+ @texture = RBGLox::Texture.new 'mosaic.tga'
33
+ @r = 0.0
34
+ @cube = RBGLox::MeshCube.new
35
+ end
36
+ def update
37
+ @r += 0.1
38
+ end
39
+ def draw
40
+ glTranslatef 0.0,0.0,-6.0
41
+ glRotatef @r, 1.0, 1.0, 1.0
42
+
43
+ @texture.bind
44
+ @cube.draw
45
+ @texture.release
46
+ end
47
+ def shutdown
48
+ @texture.free
49
+ @cube.free
50
+ end
51
+ end
52
+ ```
53
+
54
+ Now let's fire this up :)
55
+
56
+ ```ruby
57
+ DemoApp.new do |app|
58
+ app.title = 'DemoApp'
59
+ app.exec
60
+ end
61
+ ```
62
+
63
+ Additional methods you can override:
64
+
65
+ ```ruby
66
+ resize(h, w)
67
+ begin_frame
68
+ end_frame
69
+ reload(event)
70
+ ```
71
+
72
+ #### Semi-automatic resource re-loading
73
+
74
+ ```ruby
75
+ DemoApp.new do |app|
76
+ app.watch = 'data/'
77
+ app.title = 'DemoApp'
78
+ app.exec
79
+ end
80
+ ```
81
+ If the `watch` variable is not `nil` then the given directory will be watched
82
+ for any changes. (i.e file modified, file created, etc)
83
+
84
+ Every time a change is detected, the `reload(event)` method is called and you can
85
+ reload your resources.
86
+
87
+ The included `RBGLox::Texture` and `RBGLox::Shader` classes have a `reload` method
88
+ which facilitates this as illustrated in the example below.
89
+
90
+ ```ruby
91
+ ...
92
+ def reload(event)
93
+ if event.type == :modified
94
+ texture1.reload if event.path =~ /myawesometexture.tga$/
95
+ shader.reload if event.path =~ /myshader.glsl$/
96
+ ...
97
+ end
98
+ ...
99
+ end
100
+ ...
101
+ ```
102
+
103
+ ### Executable
104
+
105
+ It is also possible to use rbGLox as a cheap & rudimentary "GLSL" shader editor.
106
+
107
+ In order to create a new project do the following:
108
+
109
+ mkdir glsl-demo
110
+ cd glsl-demo
111
+ rbglox --init
112
+
113
+ This will create an empty project with one shader and one texture.
114
+
115
+ To launch "editor" just type `rbglox` in the current directory and there you go.
116
+
117
+ #### Watcher
118
+
119
+ All the resources in the current directory are "watched" for changes and will be
120
+ reloaded automatically when a change is detected.
121
+
122
+ So, if you edit the shaders or the textures they will be reloaded for you without
123
+ restarting the "editor".
124
+
125
+ #### Shaders
126
+
127
+ The shader file has the following format:
128
+
129
+ [vertex]
130
+ ...
131
+ [end]
132
+
133
+ [fragment]
134
+ ...
135
+ [end]
136
+
137
+ [uniforms]
138
+ ...
139
+ [end]
140
+
141
+ Please consult the generated `default shader` when you start a "new project" for
142
+ more details.
143
+
144
+ The shader must be named `shader.glsl` in order to be used and loaded.
145
+
146
+
147
+ #### Textures
148
+
149
+ Only textures in the TGA format are supported and they are going to be loaded
150
+ in alphabetical order. If there are more than 4 textures, only the first 4
151
+ will be loaded and assigned to the first 4 available texture units.
152
+
153
+ The textures must be named in the following format: `textureN.tga` where `N`
154
+ is a number ranging from 1 to 4.
155
+
156
+ #### Models (a.k.a Meshes)
157
+
158
+ You can choose between a Quad, a Cube (a.k.a Box) and a Teapot. The default is
159
+ the Teapot.
160
+
161
+ rbglox --model teapot
162
+
163
+ #### Controls
164
+
165
+ * Hold down the left mouse button and move the mouse in order to rotate the model.
166
+ * Use the mouse wheel to zoom in / zoom out the model.
167
+
168
+ rbMedia
169
+ -------
170
+ The bundled texture is from [lovetextures.com](http://lovetextures.com) .
171
+
172
+ Contribute
173
+ ----------
174
+ * Fork the project.
175
+ * Make your feature addition or bug fix.
176
+ * Send me a pull request. Bonus points for topic branches.
177
+ * Do **not** bump the version number.
178
+
179
+ License
180
+ -------
181
+ Copyright (c) 2011, Mihail Szabolcs
182
+
183
+ rbGLox is provided as-is under the **MIT** license. For more information
184
+ see *LICENSE* .
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
4
+
5
+ require 'rbglox'
6
+ require 'optparse'
7
+ require 'ftools'
8
+
9
+ help = <<HELP
10
+ RBGLox v#{RBGLox::VERSION}
11
+
12
+ usage: rbglox [options]
13
+
14
+ Examples:
15
+ rbglox --init
16
+ rbglox --model=teapot
17
+ rbglox --title="My GLSL Demo"
18
+
19
+ Models:
20
+ quad, cube, teapot
21
+
22
+ Options:
23
+ HELP
24
+
25
+ options =
26
+ {
27
+ 'model' => 'teapot',
28
+ 'title' => "RBGLox v#{RBGLox::VERSION}"
29
+ }
30
+ opts = OptionParser.new do |opts|
31
+ opts.banner = help
32
+
33
+ opts.on('--init', 'create an empty project in the current directory') do
34
+ options['init'] = true
35
+ end
36
+
37
+ opts.on('--model [model]', 'specify sample model') do |model|
38
+ if ['quad', 'cube', 'box', 'teapot'].include? model
39
+ options['model'] = model
40
+ end
41
+ end
42
+
43
+ opts.on('--title [title]', 'specify window title') do |title|
44
+ options['title'] = title
45
+ end
46
+
47
+ opts.on('--version', 'show version information') do
48
+ puts RBGLox::VERSION
49
+ exit 0
50
+ end
51
+ end
52
+
53
+ begin
54
+ opts.parse!
55
+ rescue OptionParser::InvalidOption => e
56
+ puts e.message
57
+ exit 1
58
+ end
59
+
60
+ def init(src, dst)
61
+ puts 'Copying shader ...'
62
+ File.copy(File.join(src, 'res/shader.glsl'), File.join(dst, 'shader.glsl'))
63
+ puts 'Copying texture ...'
64
+ File.copy(File.join(src, 'res/texture.tga'), File.join(dst, 'texture1.tga'))
65
+ puts 'Now run `rbglox` and enjoy :)'
66
+ 0
67
+ end
68
+
69
+ exit init(File.dirname(File.dirname(__FILE__)), Dir.getwd) unless options['init'].nil?
70
+
71
+ unless File.exists?(File.join(Dir.getwd, 'shader.glsl'))
72
+ puts 'Error. No `shader.glsl` found in the current directory.'
73
+ exit 1
74
+ end
75
+
76
+ unless File.exists?(File.join(Dir.getwd, 'texture1.tga'))
77
+ puts 'Warning. No `texture1.tga` found in the current directory.'
78
+ end
79
+
80
+ ShaderApp.new do |app|
81
+ app.title = options['title']
82
+ app.model = options['model']
83
+ app.watch = Dir.getwd
84
+ app.exec
85
+ end
@@ -0,0 +1,126 @@
1
+ require 'gl'
2
+ require 'glu'
3
+ require 'glut'
4
+ require 'glfw'
5
+ require 'directory_watcher'
6
+
7
+ module RBGLox
8
+ class RBGLoxException < StandardError; end
9
+ end
10
+
11
+ require 'rbglox/version'
12
+ require 'rbglox/window'
13
+ require 'rbglox/resource'
14
+ require 'rbglox/texture'
15
+ require 'rbglox/shader'
16
+ require 'rbglox/mesh'
17
+ require 'rbglox/meshquad'
18
+ require 'rbglox/meshcube'
19
+ require 'rbglox/app'
20
+
21
+ class ShaderApp < RBGLox::App
22
+ attr_accessor :model
23
+
24
+ def init
25
+ @textures = []
26
+ (1..4).each do |i|
27
+ filename = File.join watch, "texture#{i}.tga"
28
+ @textures << RBGLox::Texture.new(filename) if File.exists? filename
29
+ end
30
+
31
+ @shader = RBGLox::Shader.new File.join watch, "shader.glsl"
32
+
33
+ @z = -6.0
34
+ if model == 'quad'
35
+ @model = RBGLox::MeshQuad.new
36
+ elsif ['cube', 'box'].include? model
37
+ @model = RBGLox::MeshCube.new
38
+ else
39
+ @model = nil
40
+ @z = -30.0
41
+ end
42
+
43
+ @lastX = 0
44
+ @lastY = 0
45
+ @lastM = 0
46
+
47
+ @rotX = 0.0
48
+ @rotY = 0.0
49
+ @rotZ = 0.0
50
+ end
51
+
52
+ def update
53
+ currM = mouse_wheel?
54
+
55
+ if currM != 0
56
+ @z -= (@lastM - currM)
57
+ @lastM = currM
58
+ end
59
+
60
+ if mouse_left?
61
+ currX, currY = mouse_pos?
62
+
63
+ if @lastX > 0 and @lastY > 0
64
+ @rotX += (currY - @lastY)
65
+ @rotY += (currX - @lastX)
66
+ end
67
+
68
+ @lastX = currX
69
+ @lastY = currY
70
+ else
71
+ @lastX = 0
72
+ @lastY = 0
73
+ end
74
+
75
+ end
76
+
77
+ def draw
78
+ glTranslatef(0,0, @z)
79
+ glRotatef(@rotX, 1.0, 0.0, 0.0)
80
+ glRotatef(@rotY, 0.0, 1.0, 0.0)
81
+ glRotatef(@rotZ, 0.0, 0.0, 1.0)
82
+
83
+ @textures.each_with_index do |texture, i|
84
+ texture.bind i
85
+ end
86
+
87
+ @shader.bind
88
+ @shader['time'] = time.to_f
89
+
90
+ if @model.nil?
91
+ glutSolidTeapot(8.0)
92
+ else
93
+ @model.draw
94
+ end
95
+
96
+ @shader.release
97
+
98
+ @textures.each_with_index do |texture, i|
99
+ texture.release i
100
+ end
101
+ end
102
+
103
+ def shutdown
104
+ @textures.each do |texture|
105
+ texture.free
106
+ end
107
+ @shader.free
108
+ @model.free unless @model.nil?
109
+ end
110
+
111
+ def reload(event)
112
+ if event.type == :modified
113
+ puts "reloading #{event.path} ..."
114
+ if event.path =~ /\.glsl$/i
115
+ @shader.reload
116
+ elsif event.path =~ /\.tga$/i
117
+ @textures.each_with_index do |texture, i|
118
+ if texture.filename == event.path
119
+ texture.reload i
120
+ break
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,9 @@
1
+ # Semi-abstract Application Class
2
+ class RBGLox::App < RBGLox::Window
3
+ # Constructor
4
+ def initialize
5
+ super
6
+ yield self
7
+ end
8
+ end
9
+
@@ -0,0 +1,36 @@
1
+ # Semi-abstract Mesh Class
2
+ class RBGLox::Mesh < RBGLox::Resource
3
+ include Gl
4
+
5
+ # Constructor
6
+ def initialize(verts, texs, norms, tris)
7
+ @id = glGenLists 1
8
+
9
+ glNewList id, GL_COMPILE
10
+ glPushClientAttrib GL_CLIENT_VERTEX_ARRAY_BIT
11
+ glEnableClientState GL_VERTEX_ARRAY
12
+ glEnableClientState GL_TEXTURE_COORD_ARRAY
13
+ glEnableClientState GL_NORMAL_ARRAY
14
+ glVertexPointer 3, GL_FLOAT, 0, verts
15
+ glNormalPointer GL_FLOAT, 0, norms
16
+ glTexCoordPointer 2, GL_FLOAT, 0, texs
17
+ glDrawElements GL_TRIANGLES, tris.size, GL_UNSIGNED_INT, tris
18
+ glPopClientAttrib
19
+ glEndList
20
+ end
21
+
22
+ # Draw the mesh by calling the internal display list
23
+ def draw
24
+ glCallList id
25
+ end
26
+
27
+ # Reload the mesh
28
+ def reload
29
+ # do nothing
30
+ end
31
+
32
+ # Free the mesh by destroying the internal display list
33
+ def free
34
+ glDeleteLists id, 1
35
+ end
36
+ end
@@ -0,0 +1,99 @@
1
+ # Cube Mesh Class
2
+ class RBGLox::MeshCube < RBGLox::Mesh
3
+ # Constructor
4
+ def initialize(x=1.0, y=1.0, z=1.0, tx=0.0, ty=0.0, tz=0.0)
5
+ verts = [
6
+ -x + tx, -y + ty, -z + tz,
7
+ x + tx, -y + ty, -z + tz,
8
+ x + tx, y + ty, -z + tz,
9
+ -x + tx, y + ty, -z + tz,
10
+ -x + tx, -y + ty, z + tz,
11
+ -x + tx, y + ty, z + tz,
12
+ x + tx, y + ty, z + tz,
13
+ x + tx, -y + ty, z + tz,
14
+ -x + tx, -y + ty, -z + tz,
15
+ -x + tx, y + ty, -z + tz,
16
+ -x + tx, y + ty, z + tz,
17
+ -x + tx, -y + ty, z + tz,
18
+ x + tx, -y + ty, -z + tz,
19
+ x + tx, -y + ty, z + tz,
20
+ x + tx, y + ty, z + tz,
21
+ x + tx, y + ty, -z + tz,
22
+ -x + tx, y + ty, -z + tz,
23
+ x + tx, y + ty, -z + tz,
24
+ x + tx, y + ty, z + tz,
25
+ -x + tx, y + ty, z + tz,
26
+ -x + tx, -y + ty, -z + tz,
27
+ -x + tx, -y + ty, z + tz,
28
+ x + tx, -y + ty, z + tz,
29
+ x + tx, -y + ty, -z + tz]
30
+
31
+ norms = [
32
+ 0, 0, -1,
33
+ 0, 0, -1,
34
+ 0, 0, -1,
35
+ 0, 0, -1,
36
+ 0, 0, 1,
37
+ 0, 0, 1,
38
+ 0, 0, 1,
39
+ 0, 0, 1,
40
+ -1, 0, 0,
41
+ -1, 0, 0,
42
+ -1, 0, 0,
43
+ -1, 0, 0,
44
+ 1, 0, 0,
45
+ 1, 0, 0,
46
+ 1, 0, 0,
47
+ 1, 0, 0,
48
+ 0, 1, 0,
49
+ 0, 1, 0,
50
+ 0, 1, 0,
51
+ 0, 1, 0,
52
+ 0, -1, 0,
53
+ 0, -1, 0,
54
+ 0, -1, 0,
55
+ 0, -1, 0 ]
56
+
57
+ texs = [
58
+ 0, 0, # 0
59
+ 1, 0, # 1
60
+ 1, 1, # 2
61
+ 0, 1, # 3
62
+ 1, 0, # 4
63
+ 1, 1, # 5
64
+ 0, 1, # 6
65
+ 0, 0, # 7
66
+ 1, 0, # 8
67
+ 1, 1, # 9
68
+ 0, 1, # 10
69
+ 0, 0, # 11
70
+ 0, 0, # 12
71
+ 1, 0, # 13
72
+ 1, 1, # 14
73
+ 0, 1, # 15
74
+ 0, 0, # 16
75
+ 1, 0, # 17
76
+ 1, 1, # 18
77
+ 0, 1, # 19
78
+ 0, 1, # 20
79
+ 0, 0, # 21
80
+ 1, 0, # 22
81
+ 1, 1 ] # 23
82
+
83
+ tris = [
84
+ 0, 2, 1,
85
+ 0, 3, 2,
86
+ 4, 6, 5,
87
+ 4, 7, 6,
88
+ 8, 10, 9,
89
+ 8, 11, 10,
90
+ 12, 14, 13,
91
+ 12, 15, 14,
92
+ 16, 18, 17,
93
+ 16, 19, 18,
94
+ 20, 22, 21,
95
+ 20, 23, 22 ]
96
+
97
+ super verts, texs, norms, tris
98
+ end
99
+ end
@@ -0,0 +1,29 @@
1
+ # Quad Mesh Class
2
+ class RBGLox::MeshQuad < RBGLox::Mesh
3
+ # Constructor
4
+ def initialize(x=1.0, y=1.0)
5
+ verts = [
6
+ -x, -y, 0.0,
7
+ x, -y, 0.0,
8
+ x, y, 0.0,
9
+ -x, y, 0.0 ]
10
+
11
+ texs = [
12
+ 0.0, 0.0,
13
+ 1.0, 0.0,
14
+ 1.0, 1.0,
15
+ 0.0, 1.0 ]
16
+
17
+ norms = [
18
+ 0.0, 0.0, 1.0,
19
+ 0.0, 0.0, 1.0,
20
+ 0.0, 0.0, 1.0,
21
+ 0.0, 0.0, 1.0 ]
22
+
23
+ tris = [
24
+ 3, 2, 1,
25
+ 3, 1, 0 ]
26
+
27
+ super verts, texs, norms, tris
28
+ end
29
+ end
@@ -0,0 +1,14 @@
1
+ # Abstract Resource Class
2
+ class RBGLox::Resource
3
+ attr_reader :id
4
+
5
+ # Reload resource
6
+ def reload
7
+ raise NotImplementedError
8
+ end
9
+
10
+ # Free resource
11
+ def free
12
+ raise NotImplementedError
13
+ end
14
+ end
@@ -0,0 +1,115 @@
1
+ # GLSL Shader Class
2
+ class RBGLox::Shader < RBGLox::Resource
3
+ include Gl
4
+
5
+ attr_reader :filename, :vertex, :fragment, :uniforms
6
+
7
+ # Constructor
8
+ def initialize(filename)
9
+ @filename = filename
10
+ @id = glCreateProgram
11
+
12
+ @vertex = glCreateShader GL_VERTEX_SHADER
13
+ glAttachShader id, vertex
14
+
15
+ @fragment = glCreateShader GL_FRAGMENT_SHADER
16
+ glAttachShader id, fragment
17
+
18
+ @uniforms = []
19
+
20
+ reload
21
+ end
22
+
23
+ # Set internal GLSL uniforms
24
+ def []=(name, value)
25
+ loc = glGetUniformLocation id, name
26
+ if value.is_a? Float
27
+ glUniform1f loc, value
28
+ elsif value.is_a? Integer
29
+ glUniform1i loc, value
30
+ elsif value.is_a? Array
31
+ l = value.size
32
+ if l == 2
33
+ glUniform2fv loc, value
34
+ elsif l == 3:
35
+ glUniform3fv loc, value
36
+ elsif l == 4:
37
+ glUniform4fv loc, value
38
+ end
39
+ else
40
+ raise TypeError.new('Uniform type not supported')
41
+ end
42
+ end
43
+
44
+ # Bind the Shader
45
+ def bind
46
+ glUseProgram id
47
+
48
+ uniforms.each do |k, v|
49
+ self[k] = v
50
+ end
51
+ end
52
+
53
+ # Release the Shader
54
+ def release
55
+ glUseProgram 0
56
+ end
57
+
58
+ # Reload the Shader
59
+ def reload
60
+ content = File.read filename
61
+ vert, frag, unis = parse content
62
+
63
+ glShaderSource vertex, vert
64
+ glCompileShader vertex
65
+ log = glGetShaderInfoLog vertex
66
+ puts log
67
+
68
+ return if log =~ /error/i
69
+
70
+ glShaderSource fragment, frag
71
+ glCompileShader fragment
72
+ log = glGetShaderInfoLog fragment
73
+ puts log
74
+
75
+ return if log =~ /error/i
76
+
77
+ glLinkProgram id
78
+ log = glGetProgramInfoLog id
79
+ puts log
80
+
81
+ return if log =~ /error/i
82
+
83
+ @uniforms = unis
84
+ end
85
+
86
+ # Free the Shader
87
+ def free
88
+ glDetachShader id, vertex
89
+ glDeleteShader vertex
90
+
91
+ glDetachShader id, fragment
92
+ glDeleteShader fragment
93
+
94
+ glDeleteProgram id
95
+ end
96
+
97
+ protected
98
+
99
+ # Parse the Shader file and extract the Vertex and Fragment shaders
100
+ def parse(content)
101
+ source = []
102
+
103
+ matches = content.scan(/\[(vertex|fragment|uniforms)\]\s?(.*?\s?)\s?\[end\]/m)
104
+ matches.each do |m|
105
+ if ["vertex", "fragment"].include?(m[0])
106
+ source.push(m[1])
107
+ elsif m[0] == "uniforms"
108
+ source.push(YAML.load(m[1]))
109
+ end
110
+ end
111
+
112
+ source
113
+ end
114
+
115
+ end
@@ -0,0 +1,52 @@
1
+ # Texture Class
2
+ class RBGLox::Texture < RBGLox::Resource
3
+ include Glfw
4
+ include Gl
5
+
6
+ attr_accessor :filename, :mipmaps
7
+
8
+ # Constructor
9
+ def initialize(filename, mipmaps=false)
10
+ @filename = filename
11
+ @mipmaps = mipmaps
12
+ @id = glGenTextures(1)[0]
13
+
14
+ reload
15
+ end
16
+
17
+ # Bind the Texture
18
+ def bind(unit=0)
19
+ glActiveTexture(GL_TEXTURE0 + unit)
20
+ glBindTexture GL_TEXTURE_2D, id
21
+ end
22
+
23
+ # Release the Texture
24
+ def release(unit=0)
25
+ glActiveTexture(GL_TEXTURE0 + unit)
26
+ glBindTexture GL_TEXTURE_2D, 0
27
+ end
28
+
29
+ # Reload the Texture
30
+ def reload(unit=0)
31
+ bind unit
32
+
33
+ glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE
34
+ glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE
35
+ glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR
36
+ glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR
37
+
38
+ if mipmaps:
39
+ glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST
40
+ glfwLoadTexture2D filename, GLFW_BUILD_MIPMAPS_BIT
41
+ else
42
+ glfwLoadTexture2D filename, 0
43
+ end
44
+
45
+ release unit
46
+ end
47
+
48
+ # Free the Texture
49
+ def free
50
+ glDeleteTextures [id]
51
+ end
52
+ end
@@ -0,0 +1,3 @@
1
+ module RBGLox
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,172 @@
1
+ # Semi-abstract Window class
2
+ class RBGLox::Window
3
+ include Glfw
4
+ include Gl
5
+ include Glu
6
+ include Glut
7
+
8
+ attr_accessor :title, :width, :height, :multisample, :vsync, :watch
9
+
10
+ # Constructor
11
+ def initialize
12
+ @title = 'rbGLox'
13
+ @width = 640
14
+ @height= 480
15
+ @multisample = 0
16
+ @vsync = 0
17
+ @watch = nil
18
+ end
19
+
20
+ # Closes the currently active open window
21
+ def close
22
+ glfwCloseWindow
23
+ end
24
+
25
+ # Returns TRUE if the given key is PRESSED, otherwise FALSE
26
+ def key?(key)
27
+ glfwGetKey(key) == GLFW_PRESS
28
+ end
29
+
30
+ # Returns TRUE if the given mouse button is PRESSED, otherwise FALSE
31
+ def mouse?(button = GLFW_MOUSE_BUTTON_LEFT)
32
+ glfwGetMouseButton(button) == GLFW_PRESS
33
+ end
34
+
35
+ # Return TRUE if the left mouse button is PRESSED, otherwise FALSE
36
+ def mouse_left?
37
+ mouse?
38
+ end
39
+
40
+ # Return TRUE if the right mouse button is PRESSED, otherwise FALSE
41
+ def mouse_right?
42
+ mouse? GLFW_MOUSE_BUTTON_RIGHT
43
+ end
44
+
45
+ # Returns the current mouse position (tuple)
46
+ def mouse_pos?
47
+ glfwGetMousePos
48
+ end
49
+
50
+ # Returns the current mouse wheel delta position
51
+ def mouse_wheel?
52
+ glfwGetMouseWheel
53
+ end
54
+
55
+ # Returns the current tick count
56
+ def time
57
+ glfwGetTime
58
+ end
59
+
60
+ # Opens the window and fires up the event loop
61
+ def exec
62
+ glutInit
63
+
64
+ glfwOpenWindowHint GLFW_WINDOW_NO_RESIZE, true
65
+ #glfwOpenWindowHint GLFW_FSAA_SAMPLE, multisample
66
+
67
+ glfwOpenWindow width, height, 0, 0, 0, 0, 32, 0, GLFW_WINDOW
68
+
69
+ glfwSetWindowPos 0, 0
70
+ glfwSetWindowTitle title
71
+ glfwEnable GLFW_KEY_REPEAT
72
+ glfwSwapInterval vsync
73
+
74
+ glfwSetWindowSizeCallback lambda { |w, h| resize(w, h) }
75
+
76
+ trap('INT') do
77
+ glfwCloseWindow
78
+ end
79
+
80
+ unless watch.nil?
81
+ puts "Watching #{watch} for changes ..."
82
+ dw = DirectoryWatcher.new watch, :glob => "**/*", :pre_load => true, :interval => 1
83
+ dw.add_observer do |*args|
84
+ args.each do |event|
85
+ reload event
86
+ end
87
+ end
88
+ dw.start
89
+ end
90
+
91
+ glClearColor 0.2, 0.2, 0.2, 1
92
+ glClearDepth 1.0
93
+
94
+ glEnable GL_DEPTH_TEST
95
+ glDepthFunc GL_LEQUAL
96
+
97
+ glShadeModel GL_SMOOTH
98
+ glHint GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST
99
+
100
+ glEnable GL_TEXTURE_2D
101
+ glEnable GL_COLOR_MATERIAL
102
+ glEnable GL_NORMALIZE
103
+
104
+ puts 'init'
105
+ init
106
+
107
+ while true
108
+ break unless glfwGetWindowParam GLFW_OPENED
109
+ break if key? GLFW_KEY_ESC
110
+
111
+ update
112
+
113
+ begin_frame
114
+ draw
115
+ end_frame
116
+ end
117
+
118
+ unless watch.nil?
119
+ dw.stop
120
+ end
121
+
122
+ shutdown
123
+ puts 'shutdown'
124
+ end
125
+
126
+ # User defined initializations
127
+ def init
128
+ end
129
+
130
+ # User defined shutdown
131
+ def shutdown
132
+ end
133
+
134
+ # User defined window resize, sets up viewport and perspective projection
135
+ def resize(w, h)
136
+ glViewport 0, 0, w, h
137
+
138
+ glMatrixMode GL_PROJECTION
139
+ glLoadIdentity
140
+
141
+ gluPerspective 45.0, w.to_f/h.to_f, 0.1, 1000.0
142
+
143
+ glMatrixMode GL_MODELVIEW
144
+ glLoadIdentity
145
+ end
146
+
147
+ # User defined method called when entering a frame
148
+ def begin_frame
149
+ glClear GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT
150
+ glLoadIdentity
151
+ end
152
+
153
+ # User defined method called when leaving the frame
154
+ def end_frame
155
+ glfwSwapBuffers
156
+ end
157
+
158
+ # User defined draw method
159
+ def draw
160
+ raise NotImplementedError
161
+ end
162
+
163
+ # User defined update method
164
+ def update
165
+ # empty
166
+ end
167
+
168
+ # User defined reload event method
169
+ def reload(event)
170
+ # empty
171
+ end
172
+ end
@@ -0,0 +1,35 @@
1
+ [vertex]
2
+ uniform float time;
3
+
4
+ void main()
5
+ {
6
+ gl_FrontColor = gl_Color;
7
+ gl_TexCoord[0] = gl_MultiTexCoord0;
8
+ gl_Position = ftransform();
9
+ }
10
+ [end]
11
+
12
+ [fragment]
13
+ uniform float time;
14
+ uniform float offset;
15
+ uniform vec2 discardOffset;
16
+ uniform sampler2D tex0;
17
+ uniform sampler2D tex1;
18
+ uniform sampler2D tex2;
19
+ uniform sampler2D tex3;
20
+
21
+ void main()
22
+ {
23
+ vec2 st = gl_TexCoord[0].st;
24
+
25
+ if(st.t < discardOffset[0] || st.s < discardOffset[1])
26
+ discard;
27
+
28
+ gl_FragColor = texture2D(tex0, st * offset);
29
+ }
30
+ [end]
31
+
32
+ [uniforms]
33
+ discardOffset: [0.1, 0.1]
34
+ offset: 0.3
35
+ [end]
Binary file
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'rbglox'
4
+
5
+ class RBGLoxTest < Test::Unit::TestCase
6
+ def test_version
7
+ assert_equal RBGLox::VERSION, '0.1.0'
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rbglox
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Mihail Szabolcs
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-06-19 00:00:00 +03:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: ruby-opengl
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 237
30
+ segments:
31
+ - 0
32
+ - 60
33
+ - 1
34
+ version: 0.60.1
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: ruby-glfw
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 57
46
+ segments:
47
+ - 0
48
+ - 9
49
+ - 1
50
+ version: 0.9.1
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: directory_watcher
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 7
62
+ segments:
63
+ - 1
64
+ - 4
65
+ - 0
66
+ version: 1.4.0
67
+ type: :runtime
68
+ version_requirements: *id003
69
+ description: rbGLox is a small wrapper over the ruby-opengl, ruby-glfw.
70
+ email:
71
+ - szaby@szabster.net
72
+ executables:
73
+ - rbglox
74
+ extensions: []
75
+
76
+ extra_rdoc_files:
77
+ - README.md
78
+ - LICENSE
79
+ files:
80
+ - lib/rbglox/window.rb
81
+ - lib/rbglox/texture.rb
82
+ - lib/rbglox/resource.rb
83
+ - lib/rbglox/app.rb
84
+ - lib/rbglox/mesh.rb
85
+ - lib/rbglox/meshcube.rb
86
+ - lib/rbglox/meshquad.rb
87
+ - lib/rbglox/shader.rb
88
+ - lib/rbglox/version.rb
89
+ - lib/rbglox.rb
90
+ - res/shader.glsl
91
+ - res/texture.tga
92
+ - README.md
93
+ - LICENSE
94
+ - test/test_rbglox.rb
95
+ - bin/rbglox
96
+ has_rdoc: true
97
+ homepage: http://github.com/icebreaker/rbglox
98
+ licenses: []
99
+
100
+ post_install_message:
101
+ rdoc_options:
102
+ - --charset=UTF-8
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ hash: 3
111
+ segments:
112
+ - 0
113
+ version: "0"
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ none: false
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ hash: 3
120
+ segments:
121
+ - 0
122
+ version: "0"
123
+ requirements: []
124
+
125
+ rubyforge_project: rbglox
126
+ rubygems_version: 1.3.7
127
+ signing_key:
128
+ specification_version: 3
129
+ summary: rbGLox is a small wrapper over the ruby-opengl, ruby-glfw family by abstracting and providing some high-level interfaces for things like "Textures", "GLSL Shaders", basic "Geometry" and others.
130
+ test_files:
131
+ - test/test_rbglox.rb