Class: Ray::GL::Buffer

Inherits:
Object
  • Object
show all
Defined in:
ext/gl_buffer.c,
ext/gl_buffer.c

Overview

Buffers are a low-level way to push vertices onto the GPU so you can draw them. They are used interally by higher level classes, such as Ray::BufferRenderer; Ray also keeps global buffers to store the vertices of drawables.

Internally, it uses OpenGL VBOs and VAOs (or just sets vertex attrib pointers if VAOs aren’t available).

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type, vtype) ⇒ Object

Creates a new buffer with an arbitrary small size (256).



39
40
41
42
43
44
45
46
47
48
49
# File 'ext/gl_buffer.c', line 39

static
VALUE ray_gl_buffer_init(VALUE self, VALUE type, VALUE vtype) {
  rb_iv_set(self, "@vertex_type", vtype);

  say_buffer **ptr = NULL;
  Data_Get_Struct(self, say_buffer*, ptr);

  *ptr = say_buffer_create(ray_get_vtype(vtype), ray_buf_type(type), 256);

  return self;
}

Class Method Details

.unbindObject

Unbinds any bound buffer



58
59
60
61
62
# File 'ext/gl_buffer.c', line 58

static
VALUE ray_gl_buffer_unbind(VALUE self) {
  say_buffer_unbind();
  return Qnil;
}

.unbind_vboObject

Unbinds any bound VBO from array buffer



65
66
67
68
69
# File 'ext/gl_buffer.c', line 65

static
VALUE ray_gl_buffer_unbind_vbo(VALUE self) {
  say_buffer_unbind_vbo();
  return Qnil;
}

Instance Method Details

#[](id) ⇒ Ray::GL::Vertex, Ray::Vertex

Returns The vertex at the given index.

Parameters:

  • id (Integer)

Returns:



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'ext/gl_buffer.c', line 116

static
VALUE ray_gl_buffer_get(VALUE self, VALUE i) {
  say_buffer *buf   = ray_rb2buffer(self);
  size_t      size  = say_buffer_get_size(buf);
  size_t      index = NUM2ULONG(i);

  if (index >= size)
    return Qnil;

  VALUE klass  = rb_iv_get(self, "@vertex_type");
  VALUE object = rb_funcall(klass, RAY_METH("allocate"), 0);

  size_t byte_size  = NUM2INT(rb_iv_get(klass, "@vertex_type_size"));

  void *ptr = NULL;
  Data_Get_Struct(object, void, ptr);

  memcpy(ptr, say_buffer_get_vertex(buf, index), byte_size);

  return object;
}

#[]=(id, value) ⇒ Object

Parameters:



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'ext/gl_buffer.c', line 144

static
VALUE ray_gl_buffer_set(VALUE self, VALUE i, VALUE vertex) {
  rb_check_frozen(self);

  VALUE klass = rb_iv_get(self, "@vertex_type");
  if (!RAY_IS_A(vertex, klass)) {
    rb_raise(rb_eTypeError, "Can't convert %s into %s",
             RAY_OBJ_CLASSNAME(vertex), rb_class2name(klass));
  }

  say_buffer *buf   = ray_rb2buffer(self);
  size_t      size  = say_buffer_get_size(buf);
  size_t      index = NUM2ULONG(i);

  if (index >= size) {
    rb_raise(rb_eRangeError, "%zu is outside of range 0...%zu",
             size, index);
  }

  size_t byte_size = NUM2INT(rb_iv_get(klass, "@vertex_type_size"));

  void *ptr = NULL;
  Data_Get_Struct(vertex, void, ptr);

  memcpy(say_buffer_get_vertex(buf, index), ptr, byte_size);

  return vertex;
}

#bindObject

Binds the receiver, allowing to draw data stored in it



72
73
74
75
76
# File 'ext/gl_buffer.c', line 72

static
VALUE ray_gl_buffer_bind(VALUE self) {
  say_buffer_bind(ray_rb2buffer(self));
  return self;
}

#bind_instance_vboObject

Binds the receivers’s VBO containing instance data as an OpenGL array buffer



88
89
90
91
92
# File 'ext/gl_buffer.c', line 88

static
VALUE ray_gl_buffer_bind_instance_vbo(VALUE self) {
  say_buffer_bind_instance_vbo(ray_rb2buffer(self));
  return self;
}

#bind_vboObject

Binds the receivers’s VBO as an OpenGL array buffer



79
80
81
82
83
# File 'ext/gl_buffer.c', line 79

static
VALUE ray_gl_buffer_bind_vbo(VALUE self) {
  say_buffer_bind_vbo(ray_rb2buffer(self));
  return self;
}

#get_instance(id) ⇒ Ray::GL::Vertex::Instance

Returns The instance at the given index.

Parameters:

  • id (Integer)

Returns:



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'ext/gl_buffer.c', line 177

static
VALUE ray_gl_buffer_get_instance(VALUE self, VALUE i) {
  say_buffer *buf = ray_rb2buffer(self);

  if (!say_buffer_has_instance(buf))
    rb_raise(rb_eRuntimeError, "buffer has no instance data");

  size_t size  = say_buffer_get_instance_size(buf);
  size_t index = NUM2ULONG(i);

  if (index >= size)
    return Qnil;

  VALUE klass  = rb_const_get(rb_iv_get(self, "@vertex_type"),
                              rb_intern("Instance"));
  VALUE object = rb_funcall(klass, RAY_METH("allocate"), 0);

  size_t byte_size  = NUM2INT(rb_iv_get(klass, "@vertex_instance_size"));

  void *ptr = NULL;
  Data_Get_Struct(object, void, ptr);

  memcpy(ptr, say_buffer_get_instance(buf, index), byte_size);

  return object;
}

#has_instance?Boolean

Returns True if the buffer has instance-specific data.

Returns:

  • (Boolean)

    True if the buffer has instance-specific data



52
53
54
55
# File 'ext/gl_buffer.c', line 52

static
VALUE ray_gl_buffer_has_instance(VALUE self) {
  return say_buffer_has_instance(ray_rb2buffer(self)) ? Qtrue : Qfalse;
}

#instance_sizeInteger

Returns Amount of per-instance blocks in the buffer.

Returns:

  • (Integer)

    Amount of per-instance blocks in the buffer



370
371
372
373
374
375
376
# File 'ext/gl_buffer.c', line 370

static
VALUE ray_gl_buffer_instance_size(VALUE self) {
  say_buffer *buf = ray_rb2buffer(self);
  if (!say_buffer_has_instance(buf))
    return Qnil;
  return ULONG2NUM(say_buffer_get_instance_size(buf));
}

#instance_vboInteger

Returns The identifier of the OpenGL buffer used by the buffer to store per-instance data.

Returns:

  • (Integer)

    The identifier of the OpenGL buffer used by the buffer to store per-instance data



106
107
108
109
# File 'ext/gl_buffer.c', line 106

static
VALUE ray_gl_buffer_instance_vbo(VALUE self) {
  return ULONG2NUM(say_buffer_get_instance_vbo(ray_rb2buffer(self)));
}

#resize(size) ⇒ Object

Resizes the buffer, alsos causing it to be updated.

Parameters:

  • size (Integere)

    New size



362
363
364
365
366
367
# File 'ext/gl_buffer.c', line 362

static
VALUE ray_gl_buffer_resize(VALUE self, VALUE size) {
  rb_check_frozen(self);
  say_buffer_resize(ray_rb2buffer(self), NUM2ULONG(size));
  return self;
}

#resize_instance(size) ⇒ Object

Resizes the buffer’s instance data, alsos causing it to be updated.

Parameters:

  • size (Integere)

    (see #resize)



384
385
386
387
388
389
390
391
392
# File 'ext/gl_buffer.c', line 384

static
VALUE ray_gl_buffer_resize_instance(VALUE self, VALUE size) {
  rb_check_frozen(self);
  say_buffer *buf = ray_rb2buffer(self);
  if (!say_buffer_has_instance(buf))
    rb_raise(rb_eRuntimeError, "buffer has no per-instance data");
  say_buffer_resize_instance(buf, NUM2ULONG(size));
  return self;
}

#set_intance(id, value) ⇒ Object

Parameters:



210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
# File 'ext/gl_buffer.c', line 210

static
VALUE ray_gl_buffer_set_instance(VALUE self, VALUE i, VALUE vertex) {
  rb_check_frozen(self);

  say_buffer *buf = ray_rb2buffer(self);

  if (!say_buffer_has_instance(buf))
    rb_raise(rb_eRuntimeError, "buffer has no instance data");

  VALUE klass = rb_const_get(rb_iv_get(self, "@vertex_type"),
                              rb_intern("Instance"));
  if (!RAY_IS_A(vertex, klass)) {
    rb_raise(rb_eTypeError, "Can't convert %s into %s",
             RAY_OBJ_CLASSNAME(vertex), rb_class2name(klass));
  }

  size_t size  = say_buffer_get_instance_size(buf);
  size_t index = NUM2ULONG(i);

  if (index >= size) {
    rb_raise(rb_eRangeError, "%zu is outside of range 0...%zu",
             size, index);
  }

  size_t byte_size = NUM2INT(rb_iv_get(klass, "@vertex_instance_size"));

  void *ptr = NULL;
  Data_Get_Struct(vertex, void, ptr);

  memcpy(say_buffer_get_instance(buf, index), ptr, byte_size);

  return vertex;
}

#sizeInteger

Returns Size of the buffer (amount of vertices it contains).

Returns:

  • (Integer)

    Size of the buffer (amount of vertices it contains)



351
352
353
354
# File 'ext/gl_buffer.c', line 351

static
VALUE ray_gl_buffer_size(VALUE self) {
  return ULONG2NUM(say_buffer_get_size(ray_rb2buffer(self)));
}

#update(range = 0...size) ⇒ Object #update(first, size) ⇒ Object

Overloads:

  • #update(range = 0...size) ⇒ Object

    Updates a part of the buffer.

    Parameters:

    • range (Range<Integer>) (defaults to: 0...size)

      Indices of vertices to update

  • #update(first, size) ⇒ Object

    Parameters:

    • first (Integer)

      First vertex to update

    • size (Integer)

      Amount of vertices to update



254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
# File 'ext/gl_buffer.c', line 254

static
VALUE ray_gl_buffer_update(int argc, VALUE *argv, VALUE self) {
  say_buffer *buf       = ray_rb2buffer(self);
  size_t      max_index = say_buffer_get_size(buf);

  if (argc == 0)
    say_buffer_update(buf);
  else if (argc == 2) {
    size_t begin = NUM2ULONG(argv[0]);
    size_t end   = NUM2ULONG(argv[1]);

    if (end > max_index)
      end = max_index;

    if (begin > end || begin > max_index)
      return self;

    size_t size = (end - begin) + 1;

    say_buffer_update_part(buf, begin, size);
  }
  else {
    VALUE range;
    rb_scan_args(argc, argv, "1", &range); /* raise exception */

    size_t begin = NUM2ULONG(rb_funcall(range, RAY_METH("begin"), 0));
    size_t end   = NUM2ULONG(rb_funcall(range, RAY_METH("end"), 0));

    if (end > max_index)
      end = max_index;

    if (begin > end || begin > max_index)
      return self;

    size_t size = (end - begin) + 1;

    say_buffer_update_part(buf, begin, size);
  }

  return self;
}

#update_instance(range = 0...size) ⇒ Object #update_instance(first, size) ⇒ Object

Overloads:

  • #update_instance(range = 0...size) ⇒ Object

    Updates a part of the buffer’s instance-specific data

    Parameters:

    • range (Range<Integer>) (defaults to: 0...size)

      (see #update)



305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
# File 'ext/gl_buffer.c', line 305

static
VALUE ray_gl_buffer_update_instance(int argc, VALUE *argv, VALUE self) {
  say_buffer *buf       = ray_rb2buffer(self);
  size_t      max_index = say_buffer_get_instance_size(buf);

  if (!say_buffer_has_instance(buf))
    rb_raise(rb_eRuntimeError, "buffer has no per-instance data");

  if (argc == 0)
    say_buffer_update_instance(buf);
  else if (argc == 2) {
    size_t begin = NUM2ULONG(argv[0]);
    size_t end   = NUM2ULONG(argv[1]);

    if (end > max_index)
      end = max_index;

    if (begin > end || begin > max_index)
      return self;

    size_t size = (end - begin) + 1;

    say_buffer_update_instance_part(buf, begin, size);
  }
  else {
    VALUE range;
    rb_scan_args(argc, argv, "1", &range); /* raise exception */

    size_t begin = NUM2ULONG(rb_funcall(range, RAY_METH("begin"), 0));
    size_t end   = NUM2ULONG(rb_funcall(range, RAY_METH("end"), 0));

    if (end > max_index)
      end = max_index;

    if (begin > end || begin > max_index)
      return self;

    size_t size = (end - begin) + 1;

    say_buffer_update_instance_part(buf, begin, size);
  }

  return self;
}

#vboInteger

Returns The identifier of the OpenGL buffer used by the buffer.

Returns:

  • (Integer)

    The identifier of the OpenGL buffer used by the buffer



97
98
99
100
# File 'ext/gl_buffer.c', line 97

static
VALUE ray_gl_buffer_vbo(VALUE self) {
  return ULONG2NUM(say_buffer_get_vbo(ray_rb2buffer(self)));
}