Class: Ray::Shader

Inherits:
Object
  • Object
show all
Defined in:
lib/ray/shader.rb,
ext/shader.c

Defined Under Namespace

Classes: NoUniformError

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = nil) ⇒ Shader

Returns a new instance of Shader.

Parameters:

  • opts (Hash) (defaults to: nil)

    a customizable set of options



10
11
12
13
14
15
# File 'lib/ray/shader.rb', line 10

def initialize(opts = nil)
  @locations = {}
  @images    = {}

  compile(opts) if opts
end

Class Method Details

.geometry_available?true, falsue

Returns True if geometry shaders are available.

Returns:

  • (true, falsue)

    True if geometry shaders are available



46
47
48
49
# File 'ext/shader.c', line 46

static
VALUE ray_shader_geometry_available(VALUE self) {
  return say_shader_is_geometry_available() ? Qtrue : Qfalse;
}

.use_old!Object

Make Ray’s shaders forcefully use old (deprecated) style shaders. This should be called before the shaders get created (in the case of targets, this means before the creations of those targets)



37
38
39
40
41
# File 'ext/shader.c', line 37

static
VALUE ray_shader_use_old(VALUE self) {
  say_shader_force_old();
  return Qnil;
}

Instance Method Details

#[]=(attr, value) ⇒ Object

Parameters:

  • attr (String, Symbol)

    Name of the parameter to set



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/ray/shader.rb', line 47

def []=(attr, value)
  attr = attr.to_sym
  @locations[attr] ||= locate(attr)

  loc = @locations[attr]
  unless loc
    raise NoUniformError, attr
  end

  case value
  when Vector2
    set_vector2 loc, value
  when Vector3
    set_vector3 loc, value
  when Color
    set_color loc, value
  when Matrix
    set_matrix loc, value
  when true, false, nil
    set_bool loc, value
  when :current_texture
    set_current_texture loc
  when Image
    set_image loc, val
  when Array
    unless value.size.between? 1, 4
      raise "can't send a #{value.size}-sized vector"
    end

    set_array loc, value
  else # numeric-stuff
    set_numeric loc, value
  end
end

#apply_vertex(klass) ⇒ Object

Sets the vertex layout to use. It is required to link the vertex again for this change to be applied.

Parameters:

  • klass (Class)

    Class of the vertex to use with this shader.



126
127
128
129
130
131
132
133
134
135
136
# File 'ext/shader.c', line 126

static
VALUE ray_shader_apply_vertex(VALUE self, VALUE klass) {
  say_shader *shader = ray_rb2shader(self);

  if (klass == rb_path2class("Ray::Vertex"))
    say_shader_apply_vertex_type(shader, 0);
  else
    say_shader_apply_vertex_type(shader, ray_get_vtype(klass));

  return klass;
}

#bindObject

Binds the shader program



155
156
157
158
159
# File 'ext/shader.c', line 155

static
VALUE ray_shader_bind(VALUE self) {
  say_shader_bind(ray_rb2shader(self));
  return Qnil;
}

#compile(opts) ⇒ Object

Compiles the shader.

Parameters:

  • opts (Hash)

    a customizable set of options

Options Hash (opts):

  • :vertex (String, #read)

    A vertex shader (filename, or io)

  • :frag (String, #read)

    A fragment shader (filename, or io)

  • :geometry (String, #read)

    A geometry shader (filename, or io)



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/ray/shader.rb', line 22

def compile(opts)
  [:vertex, :frag, :geometry].each do |type|
    if opts[type]
      if opts[type].is_a? String
        opts[type] = File.read(opts[type])
      else
        opts[type] = opts[type].read
      end
    end
  end

  compile_vertex(opts[:vertex]) if opts[:vertex]
  compile_frag(opts[:frag]) if opts[:frag]
  compile_geometry(opts[:geometry]) if opts[:geometry]

  link

  @locations.clear
  @images.clear

  self
end

#compile_frag(src) ⇒ Object

Compiles the fragment shader with a new source code.

Parameters:

  • src (String)

    Source code



56
57
58
59
60
61
62
63
# File 'ext/shader.c', line 56

static
VALUE ray_shader_compile_frag(VALUE self, VALUE src) {
  if (!say_shader_compile_frag(ray_rb2shader(self), StringValuePtr(src))) {
    rb_raise(rb_path2class("Ray::Shader::CompileError"), "%s",
             say_error_get_last());
  }
  return self;
}

#compile_vertex(src) ⇒ Object

Compiles the geometry shader with a new source code.

Parameters:

  • src (String)

    Source code



86
87
88
89
90
91
92
93
94
# File 'ext/shader.c', line 86

static
VALUE ray_shader_compile_geometry(VALUE self, VALUE src) {
  if (!say_shader_compile_geometry(ray_rb2shader(self), StringValuePtr(src))) {
    rb_raise(rb_path2class("Ray::Shader::CompileError"), "%s",
             say_error_get_last());
  }

  return self;
}

#compile_vertex(src) ⇒ Object

Compiles the vertex shader with a new source code.

Parameters:

  • src (String)

    Source code



70
71
72
73
74
75
76
77
78
# File 'ext/shader.c', line 70

static
VALUE ray_shader_compile_vertex(VALUE self, VALUE src) {
  if (!say_shader_compile_vertex(ray_rb2shader(self), StringValuePtr(src))) {
    rb_raise(rb_path2class("Ray::Shader::CompileError"), "%s",
             say_error_get_last());
  }

  return self;
}

#detach_geometryObject

Detaches any geomtry shader attached to the shader.



99
100
101
102
103
# File 'ext/shader.c', line 99

static
VALUE ray_shader_detach_geometry(VALUE self) {
  say_shader_detach_geometry(ray_rb2shader(self));
  return self;
}

Links the shader. This is required once you have compiled the vertex and fragment shaders.



109
110
111
112
113
114
115
116
117
# File 'ext/shader.c', line 109

static
VALUE ray_shader_link(VALUE self) {
  if (!say_shader_link(ray_rb2shader(self))) {
    rb_raise(rb_path2class("Ray::Shader::LinkError"), "%s",
             say_error_get_last());
  }

  return Qnil;
}

#locate(name) ⇒ Integer?

Returns Location of the attribute.

Parameters:

  • name (String, Symbol)

    Name of the attribute

Returns:

  • (Integer, nil)

    Location of the attribute



143
144
145
146
147
148
149
150
151
152
# File 'ext/shader.c', line 143

static
VALUE ray_shader_locate(VALUE self, VALUE attr) {
  const char *str = rb_id2name(rb_to_id(attr));
  int loc = say_shader_locate(ray_rb2shader(self), str);

  if (loc >= 0)
    return INT2FIX(loc);
  else
    return Qnil;
}

#set_array(loc, val) ⇒ Object



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'ext/shader.c', line 188

static
VALUE ray_shader_set_array(VALUE self, VALUE loc, VALUE val) {
  rb_check_frozen(self);

  rb_hash_aset(rb_iv_get(self, "@images"), loc, Qnil);

  size_t size = RARRAY_LEN(val);

  float vector[4];
  size_t id = 0;
  switch (size) {
  case 4:
    vector[id] = NUM2DBL(RAY_ARRAY_AT(val, id));
    id++;
  case 3:
    vector[id] = NUM2DBL(RAY_ARRAY_AT(val, id));
    id++;
  case 2:
    vector[id] = NUM2DBL(RAY_ARRAY_AT(val, id));
    id++;
  case 1:
    vector[id] = NUM2DBL(RAY_ARRAY_AT(val, id));
    id++;
    break;
  default:
    rb_raise(rb_eRuntimeError, "can't send %zu-sized vector",
             size);
    return Qnil;
  }

  say_shader_set_floats_loc(ray_rb2shader(self), NUM2INT(loc),
                            size, vector);
  return val;
}

#set_bool(loc, val) ⇒ Object



249
250
251
252
253
254
255
256
# File 'ext/shader.c', line 249

static
VALUE ray_shader_set_bool(VALUE self, VALUE loc, VALUE val) {
  rb_check_frozen(self);
  rb_hash_aset(rb_iv_get(self, "@images"), loc, Qnil);
  say_shader_set_bool_loc(ray_rb2shader(self), NUM2INT(loc),
                          RTEST(val));
  return val;
}

#set_color(loc, val) ⇒ Object



179
180
181
182
183
184
185
# File 'ext/shader.c', line 179

static
VALUE ray_shader_set_color(VALUE self, VALUE loc, VALUE val) {
  rb_check_frozen(self);
  rb_hash_aset(rb_iv_get(self, "@images"), loc, Qnil);
  say_shader_set_color_loc(ray_rb2shader(self), NUM2INT(loc), ray_rb2col(val));
  return val;
}

#set_current_texture(loc) ⇒ Object



241
242
243
244
245
246
247
# File 'ext/shader.c', line 241

static
VALUE ray_shader_set_current_texture(VALUE self, VALUE loc) {
  rb_check_frozen(self);
  rb_hash_aset(rb_iv_get(self, "@images"), loc, Qnil);
  say_shader_set_current_texture_loc(ray_rb2shader(self), NUM2INT(loc));
  return Qnil;
}

#set_image(loc, val) ⇒ Object



232
233
234
235
236
237
238
239
# File 'ext/shader.c', line 232

static
VALUE ray_shader_set_image(VALUE self, VALUE loc, VALUE val) {
  rb_check_frozen(self);
  rb_hash_aset(rb_iv_get(self, "@images"), loc, val);
  say_shader_set_image_loc(ray_rb2shader(self), NUM2INT(loc),
                           ray_rb2image(val));
  return val;
}

#set_matrix(loc, val) ⇒ Object



258
259
260
261
262
263
264
265
# File 'ext/shader.c', line 258

static
VALUE ray_shader_set_matrix(VALUE self, VALUE loc, VALUE val) {
  rb_check_frozen(self);
  rb_hash_aset(rb_iv_get(self, "@images"), loc, Qnil);
  say_shader_set_matrix_loc(ray_rb2shader(self), NUM2INT(loc),
                          ray_rb2matrix(val));
  return val;
}

#set_numeric(loc, val) ⇒ Object



223
224
225
226
227
228
229
230
# File 'ext/shader.c', line 223

static
VALUE ray_shader_set_numeric(VALUE self, VALUE loc, VALUE val) {
  rb_check_frozen(self);
  rb_hash_aset(rb_iv_get(self, "@images"), loc, Qnil);
  say_shader_set_float_loc(ray_rb2shader(self), NUM2INT(loc),
                           NUM2DBL(val));
  return val;
}

#set_vector2(loc, val) ⇒ Object



161
162
163
164
165
166
167
168
# File 'ext/shader.c', line 161

static
VALUE ray_shader_set_vector2(VALUE self, VALUE loc, VALUE val) {
  rb_check_frozen(self);
  rb_hash_aset(rb_iv_get(self, "@images"), loc, Qnil);
  say_shader_set_vector2_loc(ray_rb2shader(self), NUM2INT(loc),
                             ray_convert_to_vector2(val));
  return val;
}

#set_vector3(loc, val) ⇒ Object



170
171
172
173
174
175
176
177
# File 'ext/shader.c', line 170

static
VALUE ray_shader_set_vector3(VALUE self, VALUE loc, VALUE val) {
  rb_check_frozen(self);
  rb_hash_aset(rb_iv_get(self, "@images"), loc, Qnil);
  say_shader_set_vector3_loc(ray_rb2shader(self), NUM2INT(loc),
                             ray_convert_to_vector3(val));
  return val;
}