opengl-aux 1.0.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/opengl-aux/buffer.rb +100 -0
- data/lib/opengl-aux/error.rb +57 -0
- data/lib/opengl-aux/gl.rb +372 -0
- data/lib/opengl-aux/program.rb +161 -0
- data/lib/opengl-aux/shader.rb +64 -0
- data/lib/opengl-aux/texture.rb +115 -0
- data/lib/opengl-aux/version.rb +12 -0
- data/lib/opengl-aux/vertex_array.rb +73 -0
- data/lib/opengl-aux.rb +16 -0
- metadata +88 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4d62d50a90a153ae31c7313cd71317c99edab993
|
4
|
+
data.tar.gz: 39a962d7c4c6fa4e9397f9268036637e9eddf676
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e6d810e70fcf3063e81fef2e45ddc8bbc80012d5ead1ddac9236c2d078459a6095c72b84203f023db843f8e3c870a12878daeb0ce36731e46443729dd53c99a7
|
7
|
+
data.tar.gz: 55e6b6a8992d9ba097cfe9998ea7ec527f66fcedcf6a4986577da24473c738deb41d57c8cfea0b35b2db6eeb74330119db2cf1ff48f32ef69c30840e6ccdd400
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# This file is part of the opengl-aux project.
|
2
|
+
# <https://github.com/nilium/opengl-aux>
|
3
|
+
#
|
4
|
+
# -----------------------------------------------------------------------------
|
5
|
+
#
|
6
|
+
# buffer.rb
|
7
|
+
# GL buffer object wrapper.
|
8
|
+
|
9
|
+
|
10
|
+
require 'opengl-aux/gl'
|
11
|
+
require 'opengl-aux/error'
|
12
|
+
|
13
|
+
|
14
|
+
class GL::Buffer
|
15
|
+
|
16
|
+
class << self
|
17
|
+
|
18
|
+
attr_accessor :__buffer_target_getters__
|
19
|
+
|
20
|
+
def current_binding(target)
|
21
|
+
GL.glGetInteger(__buffer_target_getters__[target])
|
22
|
+
end
|
23
|
+
|
24
|
+
def preserve_binding(target)
|
25
|
+
current = bound_name(target)
|
26
|
+
begin
|
27
|
+
yield
|
28
|
+
ensure
|
29
|
+
GL.glBindBuffer(target, current)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end # singleton_class
|
34
|
+
|
35
|
+
|
36
|
+
self.__buffer_target_getters__ = {
|
37
|
+
GL::GL_ARRAY_BUFFER => GL::GL_ARRAY_BUFFER_BINDING,
|
38
|
+
GL::GL_ATOMIC_COUNTER_BUFFER => GL::GL_ATOMIC_COUNTER_BUFFER_BINDING,
|
39
|
+
GL::GL_DISPATCH_INDIRECT_BUFFER => GL::GL_DISPATCH_INDIRECT_BUFFER_BINDING,
|
40
|
+
GL::GL_DRAW_INDIRECT_BUFFER => GL::GL_DRAW_INDIRECT_BUFFER_BINDING,
|
41
|
+
GL::GL_ELEMENT_ARRAY_BUFFER => GL::GL_ELEMENT_ARRAY_BUFFER_BINDING,
|
42
|
+
GL::GL_PIXEL_PACK_BUFFER => GL::GL_PIXEL_PACK_BUFFER_BINDING,
|
43
|
+
GL::GL_PIXEL_UNPACK_BUFFER => GL::GL_PIXEL_UNPACK_BUFFER_BINDING,
|
44
|
+
GL::GL_QUERY_BUFFER => GL::GL_QUERY_BUFFER_BINDING,
|
45
|
+
GL::GL_SHADER_STORAGE_BUFFER => GL::GL_SHADER_STORAGE_BUFFER_BINDING,
|
46
|
+
GL::GL_SHADER_STORAGE_BUFFER => GL::GL_SHADER_STORAGE_BUFFER_BINDING,
|
47
|
+
GL::GL_TEXTURE_BUFFER => GL::GL_TEXTURE_BUFFER_BINDING,
|
48
|
+
GL::GL_TRANSFORM_FEEDBACK_BUFFER => GL::GL_TRANSFORM_FEEDBACK_BUFFER_BINDING,
|
49
|
+
GL::GL_UNIFORM_BUFFER => GL::GL_UNIFORM_BUFFER_BINDING,
|
50
|
+
}
|
51
|
+
|
52
|
+
__buffer_target_getters__.default_proc = -> (hash, key) do
|
53
|
+
raise ArgumentError, "No queryable buffer binding target for #{key}"
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
attr_reader :name
|
58
|
+
attr_accessor :target
|
59
|
+
|
60
|
+
def initialize(target = nil, name = nil)
|
61
|
+
@name = (name != 0 && name) || 0
|
62
|
+
@target = target
|
63
|
+
yield self if block_given?
|
64
|
+
end
|
65
|
+
|
66
|
+
def is_buffer?
|
67
|
+
GL::glIsBuffer(@name) != GL::GL_FALSE
|
68
|
+
end
|
69
|
+
|
70
|
+
def delete
|
71
|
+
if @name != 0
|
72
|
+
GL.glDeleteBuffers(@name)
|
73
|
+
@name = 0
|
74
|
+
end
|
75
|
+
self
|
76
|
+
end
|
77
|
+
|
78
|
+
def bind(target = nil)
|
79
|
+
target ||= (@target || GL_ARRAY_BUFFER)
|
80
|
+
@target ||= target
|
81
|
+
raise ArgumentError, "No target given and no previous target" unless target
|
82
|
+
|
83
|
+
if block_given?
|
84
|
+
preserve_binding(target) do
|
85
|
+
yield self
|
86
|
+
end
|
87
|
+
else
|
88
|
+
if @name == 0
|
89
|
+
@name = GL.glGenBuffers(1)
|
90
|
+
if @name == 0
|
91
|
+
raise GL::GLCreateError, "Unable to allocate buffer object"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
GL.glBindBuffer(target, @name)
|
96
|
+
self
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end # GL::Buffer
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# This file is part of the opengl-aux project.
|
2
|
+
# <https://github.com/nilium/opengl-aux>
|
3
|
+
#
|
4
|
+
# -----------------------------------------------------------------------------
|
5
|
+
#
|
6
|
+
# error.rb
|
7
|
+
# Error types used by opengl-aux.
|
8
|
+
|
9
|
+
|
10
|
+
module GL
|
11
|
+
|
12
|
+
# Generic error that should probably be subclassed for more specific errors.
|
13
|
+
# Can be used as a catch-all for GL-specific errors.
|
14
|
+
class GLError < StandardError ; end
|
15
|
+
|
16
|
+
# An error that should be raised if a call to a glGen* or glCreate* function
|
17
|
+
# fails.
|
18
|
+
class GLCreateError < GLError ; end
|
19
|
+
|
20
|
+
# State error raised for errors returned by glGetError.
|
21
|
+
class GLStateError < GLError
|
22
|
+
attr_reader :code
|
23
|
+
|
24
|
+
def self.exception(msg = nil, code = GL::GL_NO_ERROR)
|
25
|
+
new(code, msg)
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(code, msg = nil)
|
29
|
+
@code = code
|
30
|
+
super(msg)
|
31
|
+
end
|
32
|
+
|
33
|
+
def exception(msg = nil)
|
34
|
+
if msg
|
35
|
+
self.class.exception(msg, code)
|
36
|
+
else
|
37
|
+
self
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_s
|
42
|
+
code_str =
|
43
|
+
case self.code
|
44
|
+
when GL::GL_NO_ERROR then 'NO_ERROR'
|
45
|
+
when GL::GL_INVALID_ENUM then 'INVALID_ENUM'
|
46
|
+
when GL::GL_INVALID_VALUE then 'INVALID_VALUE'
|
47
|
+
when GL::GL_INVALID_OPERATION then 'INVALID_OPERATION'
|
48
|
+
when GL::GL_INVALID_FRAMEBUFFER_OPERATION then 'INVALID_FRAMEBUFFER_OPERATION'
|
49
|
+
when GL::GL_OUT_OF_MEMORY then 'OUT_OF_MEMORY'
|
50
|
+
when GL::GL_STACK_UNDERFLOW then 'STACK_UNDERFLOW'
|
51
|
+
when GL::GL_STACK_OVERFLOW then 'STACK_OVERFLOW'
|
52
|
+
end
|
53
|
+
"#{code_str}: #{super}"
|
54
|
+
end
|
55
|
+
end # GLStateError
|
56
|
+
|
57
|
+
end # GL
|
@@ -0,0 +1,372 @@
|
|
1
|
+
# This file is part of the opengl-aux project.
|
2
|
+
# <https://github.com/nilium/opengl-aux>
|
3
|
+
#
|
4
|
+
# -----------------------------------------------------------------------------
|
5
|
+
#
|
6
|
+
# gl.rb
|
7
|
+
# Basic GL functions and typedefs for snow-data.
|
8
|
+
|
9
|
+
|
10
|
+
require 'opengl-core'
|
11
|
+
require 'snow-data'
|
12
|
+
require 'opengl-aux/error'
|
13
|
+
|
14
|
+
|
15
|
+
# Extensions to the opengl-core Gl module.
|
16
|
+
module GL
|
17
|
+
|
18
|
+
# Define snow-data typedefs for OpenGL
|
19
|
+
Snow::CStruct.alias_type(:gl_short, :short)
|
20
|
+
Snow::CStruct.alias_type(:gl_ushort, :unsigned_short)
|
21
|
+
Snow::CStruct.alias_type(:gl_half, :unsigned_short)
|
22
|
+
Snow::CStruct.alias_type(:gl_enum, :unsigned_int)
|
23
|
+
Snow::CStruct.alias_type(:gl_uint, :unsigned_int)
|
24
|
+
Snow::CStruct.alias_type(:gl_int, :int)
|
25
|
+
Snow::CStruct.alias_type(:gl_fixed, :int)
|
26
|
+
Snow::CStruct.alias_type(:gl_uint64, :uint64_t)
|
27
|
+
Snow::CStruct.alias_type(:gl_int64, :int64_t)
|
28
|
+
Snow::CStruct.alias_type(:gl_sizei, :int)
|
29
|
+
Snow::CStruct.alias_type(:gl_float, :float)
|
30
|
+
Snow::CStruct.alias_type(:gl_clampf, :float)
|
31
|
+
Snow::CStruct.alias_type(:gl_double, :double)
|
32
|
+
Snow::CStruct.alias_type(:gl_clampd, :double)
|
33
|
+
|
34
|
+
GLObject = Snow::CStruct.new { gl_uint :name }
|
35
|
+
|
36
|
+
def assert_no_gl_error(msg = nil)
|
37
|
+
error = glGetError
|
38
|
+
|
39
|
+
if error != GL_NO_ERROR
|
40
|
+
raise GLStateError.new(error), msg
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class << self
|
45
|
+
|
46
|
+
# @api private
|
47
|
+
attr_accessor :__box_types__
|
48
|
+
|
49
|
+
# @api private
|
50
|
+
#
|
51
|
+
# Temporarily allocates the given type, yields it to a block, and releases
|
52
|
+
# the allocated memory. Uses alloca if available. Any additional arguments
|
53
|
+
# to this function are forwarded to the type's allocator.
|
54
|
+
#
|
55
|
+
def __temp_alloc__(type, *args, &block)
|
56
|
+
result = nil
|
57
|
+
|
58
|
+
if type.respond_to?(:alloca)
|
59
|
+
result = type.alloca(*args, &block)
|
60
|
+
else
|
61
|
+
type.new(*args) do |p|
|
62
|
+
begin
|
63
|
+
result = yield[p]
|
64
|
+
ensure
|
65
|
+
p.free!
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
result
|
71
|
+
end
|
72
|
+
|
73
|
+
# @api private
|
74
|
+
#
|
75
|
+
# Returns a boxed type for the given typename. All boxed types contain a
|
76
|
+
# single member, 'name', which is of the boxed type. Boxed types are created
|
77
|
+
# on demand and cached.
|
78
|
+
#
|
79
|
+
def __boxed_type__(typename, &block)
|
80
|
+
box_types = (__box_types__ ||= Hash.new do |hash, type|
|
81
|
+
hash[type] = Snow::CStruct.new { __send__(type, :name) }
|
82
|
+
end)
|
83
|
+
|
84
|
+
box_types[typename]
|
85
|
+
end
|
86
|
+
|
87
|
+
# @api private
|
88
|
+
#
|
89
|
+
# Wraps a previously-defined native glGen* function that returns the given
|
90
|
+
# type of object. The glGen function returns one or more GL object names.
|
91
|
+
# If returning a single name, the return type is Fixnum, otherwise it's an
|
92
|
+
# array of Fixnums.
|
93
|
+
#
|
94
|
+
def __define_gl_gen_object_method__(name, type)
|
95
|
+
self.module_exec(name, :"#{name}__", GL.__boxed_type__(type)) do
|
96
|
+
|func_name, raw_name, box_type|
|
97
|
+
|
98
|
+
define_method(func_name, -> (count) do
|
99
|
+
return nil if count <= 0
|
100
|
+
|
101
|
+
if count == 1
|
102
|
+
GL.__temp_alloc__(box_type) do |p|
|
103
|
+
send(raw_name, count, p.address)
|
104
|
+
p.name
|
105
|
+
end
|
106
|
+
else
|
107
|
+
GL.__temp_alloc__(box_type::Array, count) do |p|
|
108
|
+
send(raw_name, count, p.address)
|
109
|
+
Array.new(count) { |i| p[i].name }
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end) # define_method
|
113
|
+
|
114
|
+
end # module_exec
|
115
|
+
end # __define_gl_get_method__
|
116
|
+
|
117
|
+
# @api private
|
118
|
+
#
|
119
|
+
# Similar to __define_gl_gen_object_method__, except for deletion. Takes
|
120
|
+
# four possible types of objects to delete: a GLObject or an array of
|
121
|
+
# GLObjects, a Fixnum, or an array of Fixnums. Any other types will raise
|
122
|
+
# an error, and any type contained by an Array that is not implicitly
|
123
|
+
# convertible to a Fixnum will also raise an error.
|
124
|
+
#
|
125
|
+
def __define_gl_delete_object_method__(name, type)
|
126
|
+
self.module_exec(name, :"#{name}__") do |func_name, raw_name|
|
127
|
+
|
128
|
+
define_method(func_name, -> (objects) do
|
129
|
+
case objects
|
130
|
+
when GLObject
|
131
|
+
send(raw_name, 1, objects.address)
|
132
|
+
when GLObject::Array
|
133
|
+
send(raw_name, objects.length, objects.address)
|
134
|
+
when Fixnum
|
135
|
+
GL.__temp_alloc__(GLObject) do |p|
|
136
|
+
p.name = objects
|
137
|
+
send(raw_name, 1, p.address)
|
138
|
+
end
|
139
|
+
when Array # Assumes an array of fixnums
|
140
|
+
GL.__temp_alloc__(GLObject::Array, objects.length) do |p|
|
141
|
+
objects.each_with_index { |e, i| p[i].name = e }
|
142
|
+
send(raw_name, p.length, p.address)
|
143
|
+
end
|
144
|
+
else
|
145
|
+
raise ArgumentError,
|
146
|
+
"Invalid object passed to #{name} for deletion: #{objects.inspect}"
|
147
|
+
end
|
148
|
+
self
|
149
|
+
end) # define_method
|
150
|
+
|
151
|
+
end # module_exec
|
152
|
+
end # __define_gl_get_method__
|
153
|
+
|
154
|
+
# @api private
|
155
|
+
#
|
156
|
+
# Defines a glGet* method that returns a single value of the given type.
|
157
|
+
#
|
158
|
+
def __define_gl_get_method__(name, type)
|
159
|
+
self.module_exec(name, :"#{name}v__", GL.__boxed_type__(type)) do
|
160
|
+
|func_name, raw_name, box_type|
|
161
|
+
|
162
|
+
define_method(func_name, -> (pname) do
|
163
|
+
GL.__temp_alloc__(box_type) do |p|
|
164
|
+
send(raw_name, pname, p.address)
|
165
|
+
p.name
|
166
|
+
end
|
167
|
+
end) # define_method
|
168
|
+
|
169
|
+
end # module_exec
|
170
|
+
end # __define_gl_get_method__
|
171
|
+
|
172
|
+
end # singleton_class
|
173
|
+
|
174
|
+
|
175
|
+
# @!method self.glGenTextures(count)
|
176
|
+
# Returns an array of generated texture names.
|
177
|
+
__define_gl_gen_object_method__ :glGenTextures, :gl_uint
|
178
|
+
# @!method self.glDeleteTextures(count, objects)
|
179
|
+
__define_gl_delete_object_method__ :glDeleteTextures, :gl_uint
|
180
|
+
|
181
|
+
# @!method self.glGenVertexArrays(count)
|
182
|
+
# Returns an array of generated vertex array object names.
|
183
|
+
__define_gl_gen_object_method__ :glGenVertexArrays, :gl_uint
|
184
|
+
# @!method self.glDeleteVertexArrays(count, objects)
|
185
|
+
__define_gl_delete_object_method__ :glDeleteVertexArrays, :gl_uint
|
186
|
+
|
187
|
+
# @!method self.glGenBuffers(count)
|
188
|
+
# Returns an array of generated buffer object names.
|
189
|
+
__define_gl_gen_object_method__ :glGenBuffers, :gl_uint
|
190
|
+
# @!method self.glDeleteBuffers(count, objects)
|
191
|
+
__define_gl_delete_object_method__ :glDeleteBuffers, :gl_uint
|
192
|
+
|
193
|
+
# @!method self.glGenQueries(count)
|
194
|
+
# Returns an array of generated query object names.
|
195
|
+
__define_gl_gen_object_method__ :glGenQueries, :gl_uint
|
196
|
+
# @!method self.glDeleteQueries(count, objects)
|
197
|
+
__define_gl_delete_object_method__ :glDeleteQueries, :gl_uint
|
198
|
+
|
199
|
+
# @!method self.glGenSamplers(count)
|
200
|
+
# Returns an array of generated sampler object names.
|
201
|
+
__define_gl_gen_object_method__ :glGenSamplers, :gl_uint
|
202
|
+
# @!method self.glDeleteSamplers(count, objects)
|
203
|
+
__define_gl_delete_object_method__ :glDeleteSamplers, :gl_uint
|
204
|
+
|
205
|
+
# @!method self.glGenFramebuffers(count)
|
206
|
+
# Returns an array of generated framebuffer object names.
|
207
|
+
__define_gl_gen_object_method__ :glGenFramebuffers, :gl_uint
|
208
|
+
# @!method self.glDeleteFramebuffers(count, objects)
|
209
|
+
__define_gl_delete_object_method__ :glDeleteFramebuffers, :gl_uint
|
210
|
+
|
211
|
+
# @!method self.glGenRenderbuffers(count)
|
212
|
+
# Returns an array of generated renderbuffer object names.
|
213
|
+
__define_gl_gen_object_method__ :glGenRenderbuffers, :gl_uint
|
214
|
+
# @!method self.glDeleteRenderbuffers(count, objects)
|
215
|
+
__define_gl_delete_object_method__ :glDeleteRenderbuffers, :gl_uint
|
216
|
+
|
217
|
+
# @!method self.glGenRenderbuffersProgramPipelines(count)
|
218
|
+
# Returns an array of generated program pipeline object names.
|
219
|
+
__define_gl_gen_object_method__ :glGenProgramPipelines, :gl_uint
|
220
|
+
# @!method self.glDeleteRenderbuffersProgramPipelines(count, objects)
|
221
|
+
__define_gl_delete_object_method__ :glDeleteProgramPipelines, :gl_uint
|
222
|
+
|
223
|
+
# @!method self.glGenRenderbuffersTrasnformFeedbacks(count)
|
224
|
+
# Returns an array of generated transform feedback objects
|
225
|
+
__define_gl_gen_object_method__ :glGenTransformFeedbacks, :gl_uint
|
226
|
+
# @!method self.glDeleteRenderbuffersTrasnformFeedbacks(count, objects)
|
227
|
+
__define_gl_delete_object_method__ :glDeleteTransformFeedbacks, :gl_uint
|
228
|
+
|
229
|
+
__define_gl_get_method__ :glGetInteger, :gl_int
|
230
|
+
__define_gl_get_method__ :glGetInteger64, :gl_int64
|
231
|
+
__define_gl_get_method__ :glGetFloat, :float
|
232
|
+
__define_gl_get_method__ :glGetDouble, :double
|
233
|
+
|
234
|
+
# @return [Boolean] Returns the boolean value of the given parameter name.
|
235
|
+
def glGetBoolean(pname)
|
236
|
+
GL.__temp_alloc__(GL.__boxed_type__(:gl_boolean)) do |p|
|
237
|
+
p.name = 0
|
238
|
+
glGetBooleanv(pname, p.address)
|
239
|
+
p.name != GL_FALSE
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
# @return [String] Returns the string value of the given parameter name.
|
244
|
+
def glGetString(name)
|
245
|
+
glGetString__(name).to_s
|
246
|
+
end
|
247
|
+
|
248
|
+
# @return [String] Returns the string value of a parameter name at a given index.
|
249
|
+
def glGetStringi(name, index)
|
250
|
+
glGetStringi__(name, index).to_s
|
251
|
+
end
|
252
|
+
|
253
|
+
# Assumes sources is a
|
254
|
+
def glShaderSource(shader, sources)
|
255
|
+
ary_len = (source_array = sources.kind_of?(Array)) ? sources.length : 1
|
256
|
+
|
257
|
+
lengths = GL.__boxed_type__(:gl_sizei)[ary_len]
|
258
|
+
pointers = GL.__boxed_type__(:intptr_t)[ary_len]
|
259
|
+
|
260
|
+
begin
|
261
|
+
assign_block = -> (src, index) do
|
262
|
+
lengths[index].name = src.bytesize
|
263
|
+
pointers[index].name = Fiddle::Pointer[src].to_i
|
264
|
+
end
|
265
|
+
|
266
|
+
if source_array
|
267
|
+
sources.each_with_index(&assign_block)
|
268
|
+
else
|
269
|
+
assign_block[sources, 0]
|
270
|
+
end
|
271
|
+
|
272
|
+
glShaderSource__(shader, ary_len, pointers.address, lengths.address)
|
273
|
+
|
274
|
+
ensure
|
275
|
+
lengths.free!
|
276
|
+
pointers.free!
|
277
|
+
end
|
278
|
+
|
279
|
+
self
|
280
|
+
end
|
281
|
+
|
282
|
+
# Returns the version or release number. Calls glGetString.
|
283
|
+
def gl_version
|
284
|
+
glGetString(GL_VERSION)
|
285
|
+
end
|
286
|
+
|
287
|
+
# Returns the implementation vendor. Calls glGetString.
|
288
|
+
def gl_vendor
|
289
|
+
glGetString(GL_VENDOR)
|
290
|
+
end
|
291
|
+
|
292
|
+
# Returns the renderer. Calls glGetString.
|
293
|
+
def gl_renderer
|
294
|
+
glGetString(GL_RENDERER)
|
295
|
+
end
|
296
|
+
|
297
|
+
# Returns the shading language version. Calls glGetString.
|
298
|
+
def gl_shading_language_version
|
299
|
+
glGetString(GL_SHADING_LANGUAGE_VERSION)
|
300
|
+
end
|
301
|
+
|
302
|
+
# Gets an array of GL extensions. This calls glGetIntegerv and glGetStringi,
|
303
|
+
# so be aware that you should probably cache the results.
|
304
|
+
def gl_extensions
|
305
|
+
Array.new(glGetInteger(GL_NUM_EXTENSIONS)) do |index|
|
306
|
+
glGetStringi(GL_EXTENSIONS, index)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
def glGetShader(shader, pname)
|
311
|
+
GL.__temp_alloc__(GL.__boxed_type__(:gl_int)) do |p|
|
312
|
+
glGetShaderiv__(shader, pname, p.address)
|
313
|
+
p.name
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
def glGetShaderInfoLog(shader)
|
318
|
+
length = glGetShader(shader, GL_INFO_LOG_LENGTH)
|
319
|
+
return '' if length == 0
|
320
|
+
output = ' ' * length
|
321
|
+
glGetShaderInfoLog__(shader, output.bytesize, 0, output)
|
322
|
+
output
|
323
|
+
end
|
324
|
+
|
325
|
+
def glGetShaderSource(shader)
|
326
|
+
length = glGetShader(shader, GL_SHADER_SOURCE_LENGTH)
|
327
|
+
return '' if length == 0
|
328
|
+
output = ' ' * length
|
329
|
+
glGetShaderInfoLog__(shader, output.bytesize, 0, output)
|
330
|
+
output
|
331
|
+
end
|
332
|
+
|
333
|
+
def glGetProgram(program, pname)
|
334
|
+
GL.__temp_alloc__(GL.__boxed_type__(:gl_int)) do |p|
|
335
|
+
glGetProgramiv__(program, pname, p.address)
|
336
|
+
p.name
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
def glGetProgramInfoLog(program)
|
341
|
+
length = glGetProgram(program, GL_INFO_LOG_LENGTH)
|
342
|
+
return '' if length == 0
|
343
|
+
output = ' ' * length
|
344
|
+
glGetProgramInfoLog__(program, output.bytesize, 0, output)
|
345
|
+
output
|
346
|
+
end
|
347
|
+
|
348
|
+
GLProgramBinary = Struct.new(:format, :data)
|
349
|
+
|
350
|
+
def glGetProgramBinary(program)
|
351
|
+
binary_length = glGetProgram(program, GL_PROGRAM_BINARY_LENGTH)
|
352
|
+
|
353
|
+
return nil if binary_length <= 0
|
354
|
+
|
355
|
+
GL.__temp_alloc__(GL.__boxed_type__(:gl_enum)) do |format_buffer; binary_buffer|
|
356
|
+
binary_buffer = ' ' * binary_length
|
357
|
+
|
358
|
+
glGetProgramBinary(
|
359
|
+
program,
|
360
|
+
binary_buffer.bytesize,
|
361
|
+
0,
|
362
|
+
format_buffer.address,
|
363
|
+
binary_buffer.address
|
364
|
+
)
|
365
|
+
|
366
|
+
GLProgramBinary[format_buffer.name, binary_buffer]
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
extend self
|
371
|
+
|
372
|
+
end # GL
|
@@ -0,0 +1,161 @@
|
|
1
|
+
# This file is part of the opengl-aux project.
|
2
|
+
# <https://github.com/nilium/opengl-aux>
|
3
|
+
#
|
4
|
+
# -----------------------------------------------------------------------------
|
5
|
+
#
|
6
|
+
# program.rb
|
7
|
+
# GL program object wrapper.
|
8
|
+
|
9
|
+
|
10
|
+
require 'opengl-aux/gl'
|
11
|
+
|
12
|
+
|
13
|
+
# Declare it just for type checking
|
14
|
+
class GL::Shader ; end
|
15
|
+
|
16
|
+
class GL::Program
|
17
|
+
|
18
|
+
|
19
|
+
class << self
|
20
|
+
|
21
|
+
def current_program
|
22
|
+
GL::glGetInteger(GL::GL_CURRENT_PROGRAM)
|
23
|
+
end
|
24
|
+
|
25
|
+
def preserve_binding
|
26
|
+
raise ArgumentError, "No block given" unless block_given?
|
27
|
+
current = current_program
|
28
|
+
begin
|
29
|
+
yield
|
30
|
+
ensure
|
31
|
+
GL.glUseProgram(current)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end # singleton_class
|
36
|
+
|
37
|
+
|
38
|
+
attr_reader :name
|
39
|
+
|
40
|
+
def initialize(name = nil)
|
41
|
+
if name
|
42
|
+
@name = name
|
43
|
+
else
|
44
|
+
@name = GL.glCreateProgram()
|
45
|
+
raise GL::GLCreateError, "Unable to allocate shader" if @name == 0
|
46
|
+
end
|
47
|
+
|
48
|
+
@uniform_locations = {}
|
49
|
+
|
50
|
+
yield self if block_given?
|
51
|
+
end
|
52
|
+
|
53
|
+
def delete
|
54
|
+
if @name != 0
|
55
|
+
GL.glDeleteProgram(@name)
|
56
|
+
@name = 0
|
57
|
+
end
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
def is_program?
|
62
|
+
GL::glIsProgram(@name) != GL::GL_FALSE
|
63
|
+
end
|
64
|
+
|
65
|
+
def load_binary(binary_format, binary_string)
|
66
|
+
GL.glProgramBinary(@name, binary_format, binary_string, binary_string.bytesize)
|
67
|
+
__reload_uniforms__ if (link_successful = linked?)
|
68
|
+
link_successful
|
69
|
+
end
|
70
|
+
|
71
|
+
def binary
|
72
|
+
GL.glGetProgramBinary(@name)
|
73
|
+
end
|
74
|
+
|
75
|
+
def __reload_uniforms__
|
76
|
+
locs = @uniform_locations
|
77
|
+
locs.each_key do |key|
|
78
|
+
locs[key] = GL.glGetUniformLocation(@name, key.to_s)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def link
|
83
|
+
GL.glLinkProgram(@name)
|
84
|
+
@link_status = nil
|
85
|
+
__reload_uniforms__ if (link_successful = linked?)
|
86
|
+
link_successful
|
87
|
+
end
|
88
|
+
|
89
|
+
def linked?
|
90
|
+
GL.glGetProgram(@name, GL::GL_LINK_STATUS) != GL::GL_FALSE
|
91
|
+
end
|
92
|
+
|
93
|
+
def valid?
|
94
|
+
GL.glValidateProgram(@name)
|
95
|
+
GL.glGetProgram(@name, GL::GL_VALIDATE_STATUS) != GL::GL_FALSE
|
96
|
+
end
|
97
|
+
|
98
|
+
def info_log
|
99
|
+
GL.glGetProgramInfoLog(@name)
|
100
|
+
end
|
101
|
+
|
102
|
+
def use
|
103
|
+
if block_given?
|
104
|
+
preserve_binding do
|
105
|
+
use
|
106
|
+
yield self
|
107
|
+
end
|
108
|
+
else
|
109
|
+
GL.glUseProgram(@name)
|
110
|
+
self
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def attach_shader(shader)
|
115
|
+
case shader
|
116
|
+
when ::GL::Shader then GL.glAttachShader(@name, shader.name)
|
117
|
+
else GL.glAttachShader(@name, shader)
|
118
|
+
end
|
119
|
+
self
|
120
|
+
end
|
121
|
+
|
122
|
+
def detach_shader(shader)
|
123
|
+
case shader
|
124
|
+
when ::GL::Shader then GL.glDetachShader(@name, shader.name)
|
125
|
+
else GL.glDetachShader(@name, shader)
|
126
|
+
end
|
127
|
+
self
|
128
|
+
end
|
129
|
+
|
130
|
+
def hint_uniform(name)
|
131
|
+
name = name.to_sym
|
132
|
+
@uniform_locations[name] ||= nil
|
133
|
+
self
|
134
|
+
end
|
135
|
+
|
136
|
+
def uniform_location(name)
|
137
|
+
uniform_sym = name.to_sym
|
138
|
+
locations = @uniform_locations
|
139
|
+
locations[uniform_sym] ||= GL.glGetUniformLocation(@name, name.to_s)
|
140
|
+
end
|
141
|
+
alias_method :[], :uniform_location
|
142
|
+
|
143
|
+
def clear_uniform_location_cache
|
144
|
+
@uniform_locations.clear
|
145
|
+
end
|
146
|
+
|
147
|
+
def subroutine_uniform_location(shader_kind, uniform_name)
|
148
|
+
GL.glGetSubroutineUniformLocation(@name, shader_kind, uniform_name)
|
149
|
+
end
|
150
|
+
|
151
|
+
def bind_attrib_location(attrib_index, attrib_name)
|
152
|
+
GL.glBindAttribLocation(@name, attrib_index, attrib_name.to_s)
|
153
|
+
self
|
154
|
+
end
|
155
|
+
|
156
|
+
def bind_frag_data_location(color_number, frag_data_name)
|
157
|
+
GL.glBindFragDataLocation(@name, color_number, frag_data_name.to_s)
|
158
|
+
self
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# This file is part of the opengl-aux project.
|
2
|
+
# <https://github.com/nilium/opengl-aux>
|
3
|
+
#
|
4
|
+
# -----------------------------------------------------------------------------
|
5
|
+
#
|
6
|
+
# shader.rb
|
7
|
+
# GL shader object wrapper.
|
8
|
+
|
9
|
+
|
10
|
+
require 'opengl-aux/gl'
|
11
|
+
|
12
|
+
|
13
|
+
class GL::Shader
|
14
|
+
|
15
|
+
attr_reader :name
|
16
|
+
attr_reader :kind
|
17
|
+
|
18
|
+
def initialize(kind, name = nil)
|
19
|
+
if name
|
20
|
+
@name = name
|
21
|
+
else
|
22
|
+
@name = GL.glCreateShader(kind)
|
23
|
+
raise GL::GLCreateError, "Unable to allocate shader" if @name == 0
|
24
|
+
end
|
25
|
+
|
26
|
+
@kind = kind
|
27
|
+
yield self if block_given?
|
28
|
+
end
|
29
|
+
|
30
|
+
def delete
|
31
|
+
if @name != 0
|
32
|
+
GL.glDeleteShader(@name)
|
33
|
+
@name = 0
|
34
|
+
end
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
def is_shader?
|
39
|
+
GL::glIsShader(@name) != GL::GL_FALSE
|
40
|
+
end
|
41
|
+
|
42
|
+
def source=(sources)
|
43
|
+
GL.glShaderSource(@name, sources)
|
44
|
+
sources
|
45
|
+
end
|
46
|
+
|
47
|
+
def source
|
48
|
+
GL.glGetShaderSource(@name)
|
49
|
+
end
|
50
|
+
|
51
|
+
def compile
|
52
|
+
GL.glCompileShader(@name)
|
53
|
+
compiled?
|
54
|
+
end
|
55
|
+
|
56
|
+
def compiled?
|
57
|
+
GL.glGetShader(@name, GL::GL_COMPILE_STATUS) != GL::GL_FALSE
|
58
|
+
end
|
59
|
+
|
60
|
+
def info_log
|
61
|
+
GL.glGetShaderInfoLog(@name)
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# This file is part of the opengl-aux project.
|
2
|
+
# <https://github.com/nilium/opengl-aux>
|
3
|
+
#
|
4
|
+
# -----------------------------------------------------------------------------
|
5
|
+
#
|
6
|
+
# texture.rb
|
7
|
+
# GL texture object wrapper.
|
8
|
+
|
9
|
+
|
10
|
+
require 'opengl-aux/gl'
|
11
|
+
require 'opengl-aux/error'
|
12
|
+
|
13
|
+
|
14
|
+
class GL::Texture
|
15
|
+
|
16
|
+
class << self
|
17
|
+
|
18
|
+
attr_accessor :__texture_target_getters__
|
19
|
+
|
20
|
+
def current_unit
|
21
|
+
GL.glGetInteger(GL::GL_ACTIVE_TEXTURE)
|
22
|
+
end
|
23
|
+
|
24
|
+
def current_binding(target)
|
25
|
+
GL.glGetInteger(__texture_target_getters__[target])
|
26
|
+
end
|
27
|
+
|
28
|
+
def preserve_unit
|
29
|
+
unit = current_unit
|
30
|
+
begin
|
31
|
+
yield
|
32
|
+
ensure
|
33
|
+
GL.glActiveTexture(unit)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Implied preserve_unit
|
38
|
+
def preserve_binding(target)
|
39
|
+
preserve_unit do
|
40
|
+
binding = current_binding(target)
|
41
|
+
begin
|
42
|
+
yield
|
43
|
+
ensure
|
44
|
+
GL.glBindTexture(target, binding)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end # singleton_class
|
50
|
+
|
51
|
+
|
52
|
+
self.__texture_target_getters__ = {
|
53
|
+
GL::GL_TEXTURE_1D => GL::GL_TEXTURE_BINDING_1D,
|
54
|
+
GL::GL_TEXTURE_2D => GL::GL_TEXTURE_BINDING_2D,
|
55
|
+
GL::GL_TEXTURE_3D => GL::GL_TEXTURE_BINDING_3D,
|
56
|
+
GL::GL_TEXTURE_1D_ARRAY => GL::GL_TEXTURE_BINDING_1D_ARRAY,
|
57
|
+
GL::GL_TEXTURE_2D_ARRAY => GL::GL_TEXTURE_BINDING_2D_ARRAY,
|
58
|
+
GL::GL_TEXTURE_RECTANGLE => GL::GL_TEXTURE_BINDING_RECTANGLE,
|
59
|
+
GL::GL_TEXTURE_CUBE_MAP => GL::GL_TEXTURE_BINDING_CUBE_MAP,
|
60
|
+
GL::GL_TEXTURE_CUBE_MAP_ARRAY => GL::GL_TEXTURE_BINDING_CUBE_MAP_ARRAY,
|
61
|
+
GL::GL_TEXTURE_BUFFER => GL::GL_TEXTURE_BINDING_BUFFER,
|
62
|
+
GL::GL_TEXTURE_2D_MULTISAMPLE => GL::GL_TEXTURE_BINDING_2D_MULTISAMPLE,
|
63
|
+
GL::GL_TEXTURE_2D_MULTISAMPLE_ARRAY => GL::GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY,
|
64
|
+
}
|
65
|
+
|
66
|
+
self.__texture_target_getters__.default_proc = -> (hash, key) do
|
67
|
+
raise ArgumentError, "No queryable texture binding target for #{key}"
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
attr_reader :name
|
72
|
+
attr_accessor :target
|
73
|
+
|
74
|
+
def initialize(target = nil, name = nil)
|
75
|
+
@name = name || 0
|
76
|
+
@target = target
|
77
|
+
yield self if block_given?
|
78
|
+
end
|
79
|
+
|
80
|
+
def is_texture?
|
81
|
+
GL::glIsTexture(@name) != GL::GL_FALSE
|
82
|
+
end
|
83
|
+
|
84
|
+
def delete
|
85
|
+
if @name != 0
|
86
|
+
GL.glDeleteTextures(@name)
|
87
|
+
@name = 0
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def bind(target = nil)
|
92
|
+
# You may think this is insane, but I assure you, it isn't.
|
93
|
+
target ||= (@target || GL_TEXTURE_2D)
|
94
|
+
@target ||= target
|
95
|
+
raise ArgumentError, "No target given and no previous target" unless target
|
96
|
+
|
97
|
+
if block_given?
|
98
|
+
self.class.preserve_binding(target) do
|
99
|
+
bind(target)
|
100
|
+
yield self
|
101
|
+
end
|
102
|
+
else
|
103
|
+
if @name == 0
|
104
|
+
@name ||= GL.glGenTextures(1)
|
105
|
+
if @name == 0
|
106
|
+
raise GL::GLCreateError, "Unable to allocate texture object"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
GL.glBindTexture(target, @name)
|
111
|
+
self
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end # GL::Texture
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# This file is part of the opengl-aux project.
|
2
|
+
# <https://github.com/nilium/opengl-aux>
|
3
|
+
#
|
4
|
+
# -----------------------------------------------------------------------------
|
5
|
+
#
|
6
|
+
# version.rb
|
7
|
+
# Version codes for opengl-aux
|
8
|
+
|
9
|
+
|
10
|
+
module GL
|
11
|
+
OPENGL_AUX_VERSION = '1.0.0.pre1'
|
12
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# This file is part of the opengl-aux project.
|
2
|
+
# <https://github.com/nilium/opengl-aux>
|
3
|
+
#
|
4
|
+
# -----------------------------------------------------------------------------
|
5
|
+
#
|
6
|
+
# vertex_array.rb
|
7
|
+
# GL vertex array object wrapper.
|
8
|
+
|
9
|
+
|
10
|
+
require 'opengl-aux/gl'
|
11
|
+
require 'opengl-aux/error'
|
12
|
+
|
13
|
+
|
14
|
+
class GL::VertexArray
|
15
|
+
|
16
|
+
class << self
|
17
|
+
|
18
|
+
def current_binding
|
19
|
+
GL.glGetInteger(GL::GL_VERTEX_ARRAY_BINDING)
|
20
|
+
end
|
21
|
+
|
22
|
+
def preserve_binding
|
23
|
+
raise ArgumentError, "No block given" unless block_given?
|
24
|
+
binding = current_binding
|
25
|
+
begin
|
26
|
+
yield
|
27
|
+
ensure
|
28
|
+
GL.glBindVertexArray(binding)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end # singleton_class
|
33
|
+
|
34
|
+
|
35
|
+
attr_reader :name
|
36
|
+
|
37
|
+
def initialize(name = nil)
|
38
|
+
@name = name || 0
|
39
|
+
yield self if block_given?
|
40
|
+
end
|
41
|
+
|
42
|
+
def delete
|
43
|
+
if @name != 0
|
44
|
+
GL.glDeleteVertexArrays(@name)
|
45
|
+
@name = 0
|
46
|
+
end
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
def is_vertex_array?
|
51
|
+
GL::glIsVertexArray(@name) != GL::GL_FALSE
|
52
|
+
end
|
53
|
+
|
54
|
+
def bind
|
55
|
+
if block_given?
|
56
|
+
self.class.preserve_binding do
|
57
|
+
bind
|
58
|
+
yield self
|
59
|
+
end
|
60
|
+
else
|
61
|
+
if @name == 0
|
62
|
+
@name = GL.glGenVertexArrays(1)
|
63
|
+
if @name == 0
|
64
|
+
raise GL::GLCreateError, "Unable to allocate vertex array object"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
GL.glBindVertexArray(@name)
|
69
|
+
self
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end # GL::VertexArray
|
data/lib/opengl-aux.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# This file is part of the opengl-aux project.
|
2
|
+
# <https://github.com/nilium/opengl-aux>
|
3
|
+
#
|
4
|
+
# -----------------------------------------------------------------------------
|
5
|
+
#
|
6
|
+
# opengl-aux.rb
|
7
|
+
# Root file of opengl-aux -- requires all relevant sub-files.
|
8
|
+
|
9
|
+
|
10
|
+
require 'opengl-aux/gl'
|
11
|
+
require 'opengl-aux/error'
|
12
|
+
require 'opengl-aux/vertex_array'
|
13
|
+
require 'opengl-aux/buffer'
|
14
|
+
require 'opengl-aux/texture'
|
15
|
+
require 'opengl-aux/shader'
|
16
|
+
require 'opengl-aux/program'
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: opengl-aux
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0.pre1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Noel Raymond Cower
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: opengl-core
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: snow-data
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.3'
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 1.3.1
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - "~>"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '1.3'
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 1.3.1
|
47
|
+
description: A collection auxiliary of functions and types to simplify using the opengl-core
|
48
|
+
gem.
|
49
|
+
email: ncower@gmail.com
|
50
|
+
executables: []
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- lib/opengl-aux.rb
|
55
|
+
- lib/opengl-aux/buffer.rb
|
56
|
+
- lib/opengl-aux/error.rb
|
57
|
+
- lib/opengl-aux/gl.rb
|
58
|
+
- lib/opengl-aux/program.rb
|
59
|
+
- lib/opengl-aux/shader.rb
|
60
|
+
- lib/opengl-aux/texture.rb
|
61
|
+
- lib/opengl-aux/version.rb
|
62
|
+
- lib/opengl-aux/vertex_array.rb
|
63
|
+
homepage: https://github.com/nilium/opengl-aux
|
64
|
+
licenses:
|
65
|
+
- Simplified BSD
|
66
|
+
metadata: {}
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options: []
|
69
|
+
require_paths:
|
70
|
+
- lib
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '2.0'
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">"
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: 1.3.1
|
81
|
+
requirements: []
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 2.2.1
|
84
|
+
signing_key:
|
85
|
+
specification_version: 4
|
86
|
+
summary: Auxiliary types and functions for OpenGL use.
|
87
|
+
test_files: []
|
88
|
+
has_rdoc:
|