Class: SFML::VertexBuffer

Inherits:
Object
  • Object
show all
Defined in:
lib/sfml/graphics/vertex_buffer.rb

Overview

GPU-resident vertex buffer. Same shape as VertexArray but the vertices live in video memory, so a draw call only ships an index/handle instead of re-uploading the geometry every frame. Useful for static meshes, large tilemaps, particle systems with mostly-static positions.

buf = SFML::VertexBuffer.new(
vertices,
primitive_type: :triangles,
usage:          :static,
)
window.draw(buf)

Update later (full or partial):

buf.update(new_vertices)              # full replace
buf.update(some_vertices, offset: 32) # patch in place

If the GPU doesn't support OpenGL vertex buffer objects, SFML::VertexBuffer.available? returns false and you should fall back to VertexArray.

Constant Summary collapse

USAGES =

VBO usage hints in CSFML enum order.

C::Graphics::VERTEX_BUFFER_USAGES
USAGE_INDEX =

Usage symbol → integer Hash.

USAGES.each_with_index.to_h.freeze
PRIMITIVE_TYPES =

Primitive type symbols in sfPrimitiveType order.

VertexArray::PRIMITIVE_TYPES
PRIMITIVE_INDEX =

Primitive symbol → integer index Hash.

VertexArray::PRIMITIVE_INDEX

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(vertices = nil, count: nil, primitive_type: :points, usage: :stream) ⇒ VertexBuffer

Build a buffer either from an Array of vertices or by giving an explicit count: to allocate empty (then fill via #update).

Raises:

  • (ArgumentError)


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/sfml/graphics/vertex_buffer.rb', line 41

def initialize(vertices = nil, count: nil, primitive_type: :points, usage: :stream)
  n = vertices ? vertices.length : Integer(count || 0)
  raise ArgumentError, "give either `vertices` or `count:`" if n.zero? && vertices.nil?

  ptype = PRIMITIVE_INDEX.fetch(primitive_type) do
    raise ArgumentError,
          "Unknown primitive type: #{primitive_type.inspect} " \
          "(expected one of #{PRIMITIVE_TYPES.inspect})"
  end
  uidx = USAGE_INDEX.fetch(usage) do
    raise ArgumentError,
          "Unknown VertexBuffer usage: #{usage.inspect} " \
          "(expected one of #{USAGES.inspect})"
  end

  ptr = C::Graphics.sfVertexBuffer_create(n, ptype, uidx)
  raise GraphicsError, "sfVertexBuffer_create returned NULL " \
               "(VBOs unavailable on this GPU?)" if ptr.null?
  @handle = FFI::AutoPointer.new(ptr, C::Graphics.method(:sfVertexBuffer_destroy))

  update(vertices) if vertices && !vertices.empty?
end

Instance Attribute Details

#handle ⇒ Object (readonly)

:nodoc:



150
151
152
# File 'lib/sfml/graphics/vertex_buffer.rb', line 150

def handle
  @handle
end

Class Method Details

.available? ⇒ Boolean

Returns the self.



35
36
37
# File 'lib/sfml/graphics/vertex_buffer.rb', line 35

def self.available?
  C::Graphics.sfVertexBuffer_isAvailable
end

.unbind ⇒ Object

Returns the self.



131
132
133
# File 'lib/sfml/graphics/vertex_buffer.rb', line 131

def self.unbind
  C::Graphics.sfVertexBuffer_bind(nil)
end

Instance Method Details

#bind ⇒ Object

Bind this VBO as the active vertex buffer for the GL pipeline. Useful when mixing raw GL with SFML rendering — pair with SFML::VertexBuffer.unbind (or any other draw) to release.



125
126
127
128
# File 'lib/sfml/graphics/vertex_buffer.rb', line 125

def bind
  C::Graphics.sfVertexBuffer_bind(@handle)
  self
end

#count ⇒ Object Also known as: size, length

Returns the count.



65
# File 'lib/sfml/graphics/vertex_buffer.rb', line 65

def count = C::Graphics.sfVertexBuffer_getVertexCount(@handle)

#draw_on(target, states_ptr = nil) ⇒ Object

Returns the draw on.



136
137
138
# File 'lib/sfml/graphics/vertex_buffer.rb', line 136

def draw_on(target, states_ptr = nil) # :nodoc:
  target._draw_native(:VertexBuffer, @handle, states_ptr)
end

#draw_range_on(target, first, count, states_ptr = nil) ⇒ Object

Draw a slice of this buffer instead of the whole thing. Useful when you've packed several meshes back-to-back and want to render one at a time.



143
144
145
146
147
148
# File 'lib/sfml/graphics/vertex_buffer.rb', line 143

def draw_range_on(target, first, count, states_ptr = nil)
  C::Graphics.public_send(
    :"#{target.class::CSFML_PREFIX}_drawVertexBufferRange",
    target.handle, @handle, Integer(first), Integer(count), states_ptr,
  )
end

#native_handle ⇒ Object

Returns the native handle.



120
# File 'lib/sfml/graphics/vertex_buffer.rb', line 120

def native_handle = C::Graphics.sfVertexBuffer_getNativeHandle(@handle)

#primitive_type ⇒ Object

Returns the primitive type.



70
71
72
# File 'lib/sfml/graphics/vertex_buffer.rb', line 70

def primitive_type
  PRIMITIVE_TYPES[C::Graphics.sfVertexBuffer_getPrimitiveType(@handle)] || :unknown
end

#primitive_type=(type) ⇒ Object

Set the primitive type.



75
76
77
78
79
80
# File 'lib/sfml/graphics/vertex_buffer.rb', line 75

def primitive_type=(type)
  idx = PRIMITIVE_INDEX.fetch(type) do
    raise ArgumentError, "Unknown primitive type: #{type.inspect}"
  end
  C::Graphics.sfVertexBuffer_setPrimitiveType(@handle, idx)
end

#update(vertices, offset: 0) ⇒ Object

Replace vertices.length slots starting at offset. Pass an array longer than the buffer to grow it (CSFML expands when offset==0 and length > current).

Raises:



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/sfml/graphics/vertex_buffer.rb', line 98

def update(vertices, offset: 0)
  n   = vertices.length
  buf = FFI::MemoryPointer.new(C::Graphics::Vertex, n)
  vertices.each_with_index do |v, i|
    slot = C::Graphics::Vertex.new(buf + i * C::Graphics::Vertex.size)
    slot[:position][:x]   = v.position.x.to_f
    slot[:position][:y]   = v.position.y.to_f
    slot[:color][:r]      = v.color.r
    slot[:color][:g]      = v.color.g
    slot[:color][:b]      = v.color.b
    slot[:color][:a]      = v.color.a
    slot[:tex_coords][:x] = v.tex_coords.x.to_f
    slot[:tex_coords][:y] = v.tex_coords.y.to_f
  end

  ok = C::Graphics.sfVertexBuffer_update(@handle, buf, n, Integer(offset))
  raise GraphicsError, "sfVertexBuffer_update failed " \
               "(buffer too small or driver rejected the upload?)" unless ok
  self
end

#usage ⇒ Object

Returns the usage.



83
84
85
# File 'lib/sfml/graphics/vertex_buffer.rb', line 83

def usage
  USAGES[C::Graphics.sfVertexBuffer_getUsage(@handle)] || :unknown
end

#usage=(value) ⇒ Object

Set the usage.



88
89
90
91
92
93
# File 'lib/sfml/graphics/vertex_buffer.rb', line 88

def usage=(value)
  idx = USAGE_INDEX.fetch(value) do
    raise ArgumentError, "Unknown VertexBuffer usage: #{value.inspect}"
  end
  C::Graphics.sfVertexBuffer_setUsage(@handle, idx)
end