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 =
C::Graphics::VERTEX_BUFFER_USAGES
USAGE_INDEX =
USAGES.each_with_index.to_h.freeze
PRIMITIVE_TYPES =
VertexArray::PRIMITIVE_TYPES
PRIMITIVE_INDEX =
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)


36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/sfml/graphics/vertex_buffer.rb', line 36

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 Error, "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

#handleObject (readonly)

:nodoc:



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

def handle
  @handle
end

Class Method Details

.available?Boolean

Returns:

  • (Boolean)


30
31
32
# File 'lib/sfml/graphics/vertex_buffer.rb', line 30

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

Instance Method Details

#countObject Also known as: size, length



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

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

#draw_on(target, states_ptr = nil) ⇒ Object

:nodoc:



111
112
113
# File 'lib/sfml/graphics/vertex_buffer.rb', line 111

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.



118
119
120
121
122
123
# File 'lib/sfml/graphics/vertex_buffer.rb', line 118

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_handleObject



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

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

#primitive_typeObject



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

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

#primitive_type=(type) ⇒ Object



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

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:



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/sfml/graphics/vertex_buffer.rb', line 88

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 Error, "sfVertexBuffer_update failed " \
               "(buffer too small or driver rejected the upload?)" unless ok
  self
end

#usageObject



74
75
76
# File 'lib/sfml/graphics/vertex_buffer.rb', line 74

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

#usage=(value) ⇒ Object



78
79
80
81
82
83
# File 'lib/sfml/graphics/vertex_buffer.rb', line 78

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