Class: SFML::Shader

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

Overview

A GLSL shader. Build one from a vertex and/or fragment source (either a file path or a literal source string), then set uniforms with bracket assignment and pass it to draw via the ‘shader:` kwarg:

shader = SFML::Shader.from_source(fragment: <<~GLSL)
  uniform sampler2D texture;
  uniform float time;
  void main() {
    vec2 uv = gl_TexCoord[0].xy;
    uv.x += sin(uv.y * 20.0 + time * 3.0) * 0.02;
    gl_FragColor = texture2D(texture, uv) * gl_Color;
  }
GLSL

shader[:time] = clock.elapsed.as_seconds
window.draw(sprite, shader: shader)

Uniform types are inferred from the Ruby value:

Float / Integer / Numeric  → float (uniform float)
true / false               → bool
SFML::Vector2              → vec2
SFML::Vector3              → vec3
SFML::Color                → vec4 (normalised RGBA)
SFML::Texture              → sampler2D
:current_texture (Symbol)  → sampler2D bound to the drawable's own texture
[a, b]                     → vec2     (floats)
[a, b, c]                  → vec3
[a, b, c, d]               → vec4

Need an int / bvec / matrix / array uniform? Use the explicit setters (#set_int, #set_ivec2, etc.) — they exist for completeness.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#handleObject (readonly)

:nodoc:



117
118
119
# File 'lib/sfml/graphics/shader.rb', line 117

def handle
  @handle
end

Class Method Details

.available?Boolean

Class-level: is GLSL available on the current GPU at all?

Returns:

  • (Boolean)


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

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

.from_file(vertex: nil, geometry: nil, fragment: nil) ⇒ Object

Build a shader from one or more source files. Any of vertex / geometry / fragment may be omitted; at least one must be present.

Raises:



45
46
47
48
49
50
51
52
# File 'lib/sfml/graphics/shader.rb', line 45

def self.from_file(vertex: nil, geometry: nil, fragment: nil)
  _check_at_least_one(vertex, geometry, fragment)
  ptr = C::Graphics.sfShader_createFromFile(
    vertex&.to_s, geometry&.to_s, fragment&.to_s,
  )
  raise Error, "sfShader_createFromFile failed (compile error or missing file?)" if ptr.null?
  _wrap(ptr)
end

.from_source(vertex: nil, geometry: nil, fragment: nil) ⇒ Object

Build a shader directly from GLSL source strings.

Raises:



55
56
57
58
59
60
# File 'lib/sfml/graphics/shader.rb', line 55

def self.from_source(vertex: nil, geometry: nil, fragment: nil)
  _check_at_least_one(vertex, geometry, fragment)
  ptr = C::Graphics.sfShader_createFromMemory(vertex, geometry, fragment)
  raise Error, "sfShader_createFromMemory failed (GLSL compile error?)" if ptr.null?
  _wrap(ptr)
end

.geometry_available?Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/sfml/graphics/shader.rb', line 39

def self.geometry_available?
  C::Graphics.sfShader_isGeometryAvailable
end

Instance Method Details

#[]=(name, value) ⇒ Object

Set a uniform by name. Dispatches to the right CSFML setter based on the Ruby value’s type — see the class-level docs for the table.



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/sfml/graphics/shader.rb', line 64

def []=(name, value)
  n = name.to_s
  case value
  when true, false
    C::Graphics.sfShader_setBoolUniform(@handle, n, value)
  when Integer
    C::Graphics.sfShader_setFloatUniform(@handle, n, value.to_f)
  when Numeric
    C::Graphics.sfShader_setFloatUniform(@handle, n, value.to_f)
  when Vector2
    v = C::System::Vector2f.new
    v[:x] = value.x.to_f; v[:y] = value.y.to_f
    C::Graphics.sfShader_setVec2Uniform(@handle, n, v)
  when Vector3
    v = C::System::Vector3f.new
    v[:x] = value.x.to_f; v[:y] = value.y.to_f; v[:z] = value.z.to_f
    C::Graphics.sfShader_setVec3Uniform(@handle, n, v)
  when Color
    C::Graphics.sfShader_setColorUniform(@handle, n, value.to_native)
  when Texture
    C::Graphics.sfShader_setTextureUniform(@handle, n, value.handle)
  when :current_texture
    C::Graphics.sfShader_setCurrentTextureUniform(@handle, n)
  when Array
    case value.length
    when 2 then self[name] = Vector2.new(*value)
    when 3 then self[name] = Vector3.new(*value)
    when 4
      v = C::Graphics::GlslVec4.new
      v[:x] = value[0].to_f; v[:y] = value[1].to_f
      v[:z] = value[2].to_f; v[:w] = value[3].to_f
      C::Graphics.sfShader_setVec4Uniform(@handle, n, v)
    else
      raise ArgumentError, "Shader uniform array must be length 2, 3, or 4 (got #{value.length})"
    end
  else
    raise ArgumentError,
          "Shader uniform value must be Numeric, Vector2/3, Color, Texture, " \
          "Array of 2-4 numbers, or :current_texture (got #{value.class})"
  end
end

#set_int(name, value) ⇒ Object

Explicit integer setters when a uniform really is ‘uniform int n`.



107
108
109
# File 'lib/sfml/graphics/shader.rb', line 107

def set_int(name, value)
  C::Graphics.sfShader_setIntUniform(@handle, name.to_s, Integer(value))
end

#set_ivec2(name, x, y) ⇒ Object



111
112
113
114
115
# File 'lib/sfml/graphics/shader.rb', line 111

def set_ivec2(name, x, y)
  v = C::System::Vector2i.new
  v[:x] = Integer(x); v[:y] = Integer(y)
  C::Graphics.sfShader_setIvec2Uniform(@handle, name.to_s, v)
end