danabr75-ashton 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +0 -0
  3. data/LICENSE +21 -0
  4. data/README.md +95 -0
  5. data/Rakefile +42 -0
  6. data/examples/bloom_example.rb +59 -0
  7. data/examples/lighting_example.rb +127 -0
  8. data/examples/media/Earth.png +0 -0
  9. data/examples/media/LargeStar.png +0 -0
  10. data/examples/media/SmallStar.png +0 -0
  11. data/examples/media/Star.png +0 -0
  12. data/examples/media/Starfighter.bmp +0 -0
  13. data/examples/media/Starfighter.png +0 -0
  14. data/examples/media/simple.png +0 -0
  15. data/examples/noise_example.rb +94 -0
  16. data/examples/outline_example.rb +86 -0
  17. data/examples/particle_emitter_example.rb +114 -0
  18. data/examples/pixelate_example.rb +52 -0
  19. data/examples/pixelated_texture_example.rb +69 -0
  20. data/examples/radial_blur_example.rb +61 -0
  21. data/examples/shader_image_example.rb +75 -0
  22. data/examples/shockwave_example.rb +75 -0
  23. data/examples/stencil_shader_example.rb +104 -0
  24. data/examples/texture_render_example.rb +54 -0
  25. data/examples/tv_screen_and_static_example.rb +60 -0
  26. data/ext/ashton/GLee.c +18170 -0
  27. data/ext/ashton/GLee.h +17648 -0
  28. data/ext/ashton/ashton.c +42 -0
  29. data/ext/ashton/ashton.h +31 -0
  30. data/ext/ashton/color.c +45 -0
  31. data/ext/ashton/color.h +25 -0
  32. data/ext/ashton/common.h +41 -0
  33. data/ext/ashton/extconf.rb +45 -0
  34. data/ext/ashton/fast_math.c +30 -0
  35. data/ext/ashton/fast_math.h +30 -0
  36. data/ext/ashton/font.c +8 -0
  37. data/ext/ashton/font.h +16 -0
  38. data/ext/ashton/gosu.c +18 -0
  39. data/ext/ashton/gosu.h +19 -0
  40. data/ext/ashton/image.c +8 -0
  41. data/ext/ashton/image.h +16 -0
  42. data/ext/ashton/particle_emitter.c +788 -0
  43. data/ext/ashton/particle_emitter.h +171 -0
  44. data/ext/ashton/pixel_cache.c +237 -0
  45. data/ext/ashton/pixel_cache.h +58 -0
  46. data/ext/ashton/shader.c +9 -0
  47. data/ext/ashton/shader.h +16 -0
  48. data/ext/ashton/texture.c +442 -0
  49. data/ext/ashton/texture.h +63 -0
  50. data/ext/ashton/vendor/gl/include/GL/GL.H +1526 -0
  51. data/ext/ashton/window.c +8 -0
  52. data/ext/ashton/window.h +16 -0
  53. data/lib/ashton.rb +38 -0
  54. data/lib/ashton/gosu_ext/color.rb +25 -0
  55. data/lib/ashton/gosu_ext/font.rb +58 -0
  56. data/lib/ashton/gosu_ext/gosu_module.rb +16 -0
  57. data/lib/ashton/gosu_ext/image.rb +96 -0
  58. data/lib/ashton/gosu_ext/window.rb +79 -0
  59. data/lib/ashton/image_stub.rb +33 -0
  60. data/lib/ashton/lighting/light_source.rb +146 -0
  61. data/lib/ashton/lighting/manager.rb +98 -0
  62. data/lib/ashton/mixins/version_checking.rb +23 -0
  63. data/lib/ashton/particle_emitter.rb +87 -0
  64. data/lib/ashton/pixel_cache.rb +24 -0
  65. data/lib/ashton/shader.rb +386 -0
  66. data/lib/ashton/shaders/bloom.frag +41 -0
  67. data/lib/ashton/shaders/color_inversion.frag +11 -0
  68. data/lib/ashton/shaders/contrast.frag +16 -0
  69. data/lib/ashton/shaders/default.frag +22 -0
  70. data/lib/ashton/shaders/default.vert +14 -0
  71. data/lib/ashton/shaders/fade.frag +14 -0
  72. data/lib/ashton/shaders/grayscale.frag +15 -0
  73. data/lib/ashton/shaders/include/classicnoise2d.glsl +113 -0
  74. data/lib/ashton/shaders/include/classicnoise3d.glsl +177 -0
  75. data/lib/ashton/shaders/include/classicnoise4d.glsl +302 -0
  76. data/lib/ashton/shaders/include/noise2d.glsl +70 -0
  77. data/lib/ashton/shaders/include/noise3d.glsl +102 -0
  78. data/lib/ashton/shaders/include/noise4d.glsl +128 -0
  79. data/lib/ashton/shaders/include/rand.glsl +5 -0
  80. data/lib/ashton/shaders/lighting/distort.frag +57 -0
  81. data/lib/ashton/shaders/lighting/draw_shadows.frag +60 -0
  82. data/lib/ashton/shaders/lighting/shadow_blur.frag +60 -0
  83. data/lib/ashton/shaders/mezzotint.frag +22 -0
  84. data/lib/ashton/shaders/multitexture2.vert +19 -0
  85. data/lib/ashton/shaders/outline.frag +45 -0
  86. data/lib/ashton/shaders/pixelate.frag +48 -0
  87. data/lib/ashton/shaders/radial_blur.frag +63 -0
  88. data/lib/ashton/shaders/sepia.frag +26 -0
  89. data/lib/ashton/shaders/shockwave.frag +38 -0
  90. data/lib/ashton/shaders/signed_distance_field.frag +80 -0
  91. data/lib/ashton/shaders/static.frag +25 -0
  92. data/lib/ashton/shaders/stencil.frag +27 -0
  93. data/lib/ashton/shaders/tv_screen.frag +23 -0
  94. data/lib/ashton/signed_distance_field.rb +151 -0
  95. data/lib/ashton/texture.rb +186 -0
  96. data/lib/ashton/version.rb +3 -0
  97. data/lib/ashton/window_buffer.rb +16 -0
  98. data/spec/ashton/ashton_spec.rb +22 -0
  99. data/spec/ashton/gosu_ext/color_spec.rb +34 -0
  100. data/spec/ashton/gosu_ext/font_spec.rb +57 -0
  101. data/spec/ashton/gosu_ext/gosu_spec.rb +11 -0
  102. data/spec/ashton/gosu_ext/image_spec.rb +66 -0
  103. data/spec/ashton/gosu_ext/window_spec.rb +71 -0
  104. data/spec/ashton/image_stub_spec.rb +46 -0
  105. data/spec/ashton/particle_emitter_spec.rb +123 -0
  106. data/spec/ashton/pixel_cache_spec.rb +153 -0
  107. data/spec/ashton/shader_spec.rb +152 -0
  108. data/spec/ashton/signed_distance_field_spec.rb +163 -0
  109. data/spec/ashton/texture_spec.rb +347 -0
  110. data/spec/helper.rb +12 -0
  111. metadata +309 -0
@@ -0,0 +1,9 @@
1
+ #include "shader.h"
2
+
3
+ VALUE rb_cShader;
4
+
5
+ // ----------------------------------------
6
+ void Init_Ashton_Shader(VALUE module)
7
+ {
8
+ rb_cShader = rb_define_class_under(module, "Shader", rb_cObject);
9
+ }
@@ -0,0 +1,16 @@
1
+ /*
2
+ * class Ashton::Shader
3
+ *
4
+ *
5
+ */
6
+
7
+
8
+ #ifndef ASHTON_SHADER_H
9
+ #define ASHTON_SHADER_H
10
+
11
+ #include "common.h"
12
+
13
+ void Init_Ashton_Shader(VALUE module);
14
+
15
+ #endif // ASHTON_SHADER_H
16
+
@@ -0,0 +1,442 @@
1
+ #include "texture.h"
2
+
3
+ VALUE rb_cTexture;
4
+
5
+ // Helpers
6
+ static VALUE texture_allocate(VALUE klass);
7
+ static void texture_mark(Texture* texture);
8
+ static void texture_free(Texture* texture);
9
+ static void ensure_cache_exists(VALUE self, Texture* texture);
10
+ static void ensure_fbo_exists(Texture* texture);
11
+
12
+ void Init_Ashton_Texture(VALUE module)
13
+ {
14
+ rb_cTexture = rb_define_class_under(module, "Texture", rb_cObject);
15
+
16
+ rb_define_alloc_func(rb_cTexture, texture_allocate);
17
+
18
+ rb_define_protected_method(rb_cTexture, "initialize_", Ashton_Texture_init, 3);
19
+ rb_define_protected_method(rb_cTexture, "render_", Ashton_Texture_render, 0);
20
+
21
+ rb_define_method(rb_cTexture, "cache", Ashton_Texture_get_cache, 0);
22
+
23
+ rb_define_method(rb_cTexture, "width", Ashton_Texture_get_width, 0);
24
+ rb_define_method(rb_cTexture, "height", Ashton_Texture_get_height, 0);
25
+ rb_define_method(rb_cTexture, "fbo_id", Ashton_Texture_get_fbo_id, 0);
26
+ rb_define_method(rb_cTexture, "id", Ashton_Texture_get_id, 0);
27
+
28
+ rb_define_method(rb_cTexture, "[]", Ashton_Texture_get_pixel, 2);
29
+ rb_define_method(rb_cTexture, "rgba", Ashton_Texture_get_rgba_array, 2);
30
+ rb_define_method(rb_cTexture, "red", Ashton_Texture_get_red, 2);
31
+ rb_define_method(rb_cTexture, "green", Ashton_Texture_get_green, 2);
32
+ rb_define_method(rb_cTexture, "blue", Ashton_Texture_get_blue, 2);
33
+ rb_define_method(rb_cTexture, "alpha", Ashton_Texture_get_alpha, 2);
34
+
35
+ rb_define_method(rb_cTexture, "transparent?", Ashton_Texture_is_transparent, 2);
36
+ rb_define_method(rb_cTexture, "refresh_cache", Ashton_Texture_refresh_cache, 0);
37
+ rb_define_method(rb_cTexture, "to_blob", Ashton_Texture_to_blob, 0);
38
+ rb_define_method(rb_cTexture, "draw", Ashton_Texture_draw, -1);
39
+ }
40
+
41
+ //
42
+ VALUE Ashton_Texture_get_width(VALUE self)
43
+ {
44
+ TEXTURE();
45
+ return UINT2NUM(texture->width);
46
+ }
47
+
48
+ //
49
+ VALUE Ashton_Texture_get_height(VALUE self)
50
+ {
51
+ TEXTURE();
52
+ return UINT2NUM(texture->height);
53
+ }
54
+
55
+ //
56
+ static void ensure_fbo_exists(Texture* texture)
57
+ {
58
+ if(!texture->fbo_id)
59
+ {
60
+ glGenFramebuffersEXT(1, &texture->fbo_id);
61
+
62
+ // Bind our already existing texture to the FBO.
63
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, texture->fbo_id);
64
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
65
+ GL_TEXTURE_2D, texture->id, 0);
66
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
67
+ }
68
+ }
69
+
70
+ VALUE Ashton_Texture_get_fbo_id(VALUE self)
71
+ {
72
+ TEXTURE();
73
+ ensure_fbo_exists(texture);
74
+ return UINT2NUM(texture->fbo_id);
75
+ }
76
+
77
+ VALUE Ashton_Texture_get_id(VALUE self)
78
+ {
79
+ TEXTURE();
80
+ return UINT2NUM(texture->id);
81
+ }
82
+
83
+ //
84
+ VALUE Ashton_Texture_init(VALUE self, VALUE width, VALUE height, VALUE blob)
85
+ {
86
+ TEXTURE();
87
+
88
+ if(!GL_EXT_framebuffer_object)
89
+ {
90
+ rb_raise(rb_eRuntimeError, "Ashton::Texture requires GL_EXT_framebuffer_object, which is not supported by OpenGL");
91
+ }
92
+
93
+ texture->width = NUM2UINT(width);
94
+ texture->height = NUM2UINT(height);
95
+
96
+ texture->rb_cache = Qnil;
97
+
98
+ // Create the texture.
99
+ glGenTextures(1, &texture->id);
100
+ glBindTexture(GL_TEXTURE_2D, texture->id);
101
+
102
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
103
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
104
+ // MAG_FILTER set on each draw
105
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
106
+
107
+ // Create the texture, either undefined or based on RGBA blob data string.
108
+ char* data;
109
+ if(NIL_P(blob))
110
+ {
111
+ data = NULL; // Create an empty texture, that might be filled with junk.
112
+ }
113
+ else
114
+ {
115
+ data = StringValuePtr(blob); // Create from blob data.
116
+ }
117
+
118
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texture->width,
119
+ texture->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
120
+
121
+ // Ensure the texture was created.
122
+ GLint created_width;
123
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &created_width);
124
+ if(created_width == 0) {
125
+ rb_raise(rb_eArgError, "Unable to create a texture of size %dx%d",
126
+ texture->width, texture->height);
127
+ }
128
+
129
+ // Be as lazy as possible in creating the actual FBO :)
130
+
131
+ return Qnil;
132
+ }
133
+
134
+ VALUE Ashton_Texture_render(VALUE self)
135
+ {
136
+ TEXTURE();
137
+
138
+ ensure_fbo_exists(texture);
139
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, texture->fbo_id);
140
+
141
+ return Qnil;
142
+ }
143
+
144
+ //
145
+ static VALUE texture_allocate(VALUE klass)
146
+ {
147
+ Texture* texture = ALLOC(Texture);
148
+ memset(texture, 0, sizeof(Texture));
149
+
150
+ return Data_Wrap_Struct(klass, texture_mark, texture_free, texture);
151
+ }
152
+
153
+ //
154
+ static void texture_mark(Texture* texture)
155
+ {
156
+ if(!NIL_P(texture->rb_cache)) rb_gc_mark(texture->rb_cache);
157
+ }
158
+
159
+ //
160
+ static void texture_free(Texture* texture)
161
+ {
162
+ // FBO might never have been created.
163
+ if(texture->fbo_id) glDeleteFramebuffersEXT(1, &texture->fbo_id);
164
+
165
+ glDeleteTextures(1, &texture->id);
166
+ xfree(texture);
167
+ }
168
+
169
+ //
170
+ void ensure_cache_exists(VALUE self, Texture* texture)
171
+ {
172
+ if(NIL_P(texture->rb_cache))
173
+ {
174
+ texture->rb_cache = rb_funcall(rb_cPixelCache, rb_intern("new"), 1, self);
175
+ }
176
+ }
177
+
178
+ // Returns the cache. Creates it if necessary.
179
+ VALUE Ashton_Texture_get_cache(VALUE self)
180
+ {
181
+ TEXTURE();
182
+ ensure_cache_exists(self, texture);
183
+ return texture->rb_cache;
184
+ }
185
+
186
+ //
187
+ VALUE Ashton_Texture_get_pixel(VALUE self, VALUE x, VALUE y)
188
+ {
189
+ TEXTURE();
190
+ ensure_cache_exists(self, texture);
191
+ return Ashton_PixelCache_get_pixel(texture->rb_cache, x, y);
192
+ }
193
+
194
+ VALUE Ashton_Texture_get_rgba_array(VALUE self, VALUE x, VALUE y)
195
+ {
196
+ TEXTURE();
197
+ ensure_cache_exists(self, texture);
198
+ return Ashton_PixelCache_get_rgba_array(texture->rb_cache, x, y);
199
+ }
200
+
201
+ //
202
+ VALUE Ashton_Texture_get_red(VALUE self, VALUE x, VALUE y)
203
+ {
204
+ TEXTURE();
205
+ ensure_cache_exists(self, texture);
206
+ return Ashton_PixelCache_get_red(texture->rb_cache, x, y);
207
+ }
208
+
209
+ //
210
+ VALUE Ashton_Texture_get_green(VALUE self, VALUE x, VALUE y)
211
+ {
212
+ TEXTURE();
213
+ ensure_cache_exists(self, texture);
214
+ return Ashton_PixelCache_get_green(texture->rb_cache, x, y);
215
+ }
216
+
217
+ //
218
+ VALUE Ashton_Texture_get_blue(VALUE self, VALUE x, VALUE y)
219
+ {
220
+ TEXTURE();
221
+ ensure_cache_exists(self, texture);
222
+ return Ashton_PixelCache_get_blue(texture->rb_cache, x, y);
223
+ }
224
+
225
+ //
226
+ VALUE Ashton_Texture_get_alpha(VALUE self, VALUE x, VALUE y)
227
+ {
228
+ TEXTURE();
229
+ ensure_cache_exists(self, texture);
230
+ return Ashton_PixelCache_get_alpha(texture->rb_cache, x, y);
231
+ }
232
+
233
+ //
234
+ VALUE Ashton_Texture_is_transparent(VALUE self, VALUE x, VALUE y)
235
+ {
236
+ TEXTURE();
237
+ ensure_cache_exists(self, texture);
238
+ return Ashton_PixelCache_is_transparent(texture->rb_cache, x, y);
239
+ }
240
+
241
+ VALUE Ashton_Texture_refresh_cache(VALUE self)
242
+ {
243
+ TEXTURE();
244
+ ensure_cache_exists(self, texture);
245
+ return Ashton_PixelCache_refresh(texture->rb_cache);
246
+ }
247
+
248
+ VALUE Ashton_Texture_to_blob(VALUE self)
249
+ {
250
+ TEXTURE();
251
+ ensure_cache_exists(self, texture);
252
+ return Ashton_PixelCache_to_blob(texture->rb_cache);
253
+ }
254
+
255
+ // ----------------------------------------
256
+ static VALUE draw_block(VALUE yield_value, VALUE parameters, int argc, VALUE argv[])
257
+ {
258
+ VALUE self = rb_ary_entry(parameters, 0);
259
+ float x = (float)NUM2DBL(rb_ary_entry(parameters, 1));
260
+ float y = (float)NUM2DBL(rb_ary_entry(parameters, 2));
261
+ VALUE blend_mode = rb_ary_entry(parameters, 3);
262
+ VALUE color = rb_ary_entry(parameters, 4);
263
+ VALUE shader = rb_ary_entry(parameters, 5);
264
+ VALUE multitexture = rb_ary_entry(parameters, 6);
265
+ VALUE pixelated = rb_ary_entry(parameters, 7);
266
+
267
+ TEXTURE(); // Uses 'self' value, so can't be at start of function.
268
+
269
+ if(!NIL_P(shader))
270
+ {
271
+ VALUE options = rb_hash_new();
272
+ rb_hash_aset(options, SYMBOL("required"), Qfalse);
273
+
274
+ VALUE location = rb_funcall(shader, rb_intern("send"), 3, SYMBOL("uniform_location"), SYMBOL("texture_enabled"), options);
275
+ if(FIX2INT(location) != -1)
276
+ {
277
+ rb_funcall(shader, rb_intern("send"), 3, SYMBOL("set_uniform"), location, Qtrue);
278
+ }
279
+ rb_funcall(shader, rb_intern("color="), 1, color);
280
+ }
281
+
282
+ glEnable(GL_BLEND);
283
+ glEnable(GL_TEXTURE_2D);
284
+ glBindTexture(GL_TEXTURE_2D, texture->id);
285
+
286
+ // Pixelate or smooth, depending on preference.
287
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
288
+ RTEST(pixelated) ? GL_NEAREST : GL_LINEAR);
289
+
290
+ // Set blending mode.
291
+ // Don't need an 'else' clause, since we checked before.
292
+ ID blend_id = SYM2ID(blend_mode);
293
+ if(blend_id == rb_intern(DRAW_MODE_ALPHA_BLEND))
294
+ {
295
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
296
+ }
297
+ else if(blend_id == rb_intern(DRAW_MODE_ADD))
298
+ {
299
+ glBlendFunc(GL_ONE, GL_ONE);
300
+ }
301
+ else if(blend_id == rb_intern(DRAW_MODE_MULTIPLY))
302
+ {
303
+ glBlendFunc(GL_DST_COLOR, GL_ZERO);
304
+ }
305
+ else if(blend_id == rb_intern(DRAW_MODE_REPLACE))
306
+ {
307
+ glBlendFunc(GL_ONE, GL_ZERO);
308
+ }
309
+
310
+ // Enable multitexturing.
311
+ if(!NIL_P(multitexture))
312
+ {
313
+ uint texture_id = NUM2UINT(rb_funcall(multitexture, rb_intern("id"), 0));
314
+ glActiveTexture(GL_TEXTURE1);
315
+ glBindTexture(GL_TEXTURE_2D, texture_id);
316
+ }
317
+
318
+ glBegin(GL_QUADS);
319
+ glTexCoord2d(0.0, 0.0);
320
+ glMultiTexCoord2d(GL_TEXTURE1, 0.0, 0.0);
321
+ glVertex2d(x, y + texture->height); // BL
322
+
323
+ glTexCoord2d(0.0, 1.0);
324
+ glMultiTexCoord2d(GL_TEXTURE1, 0.0, 1.0);
325
+ glVertex2d(x, y); // TL
326
+
327
+ glTexCoord2d(1.0, 1.0);
328
+ glMultiTexCoord2d(GL_TEXTURE1, 1.0, 1.0);
329
+ glVertex2d(x + texture->width, y); // TR
330
+
331
+ glTexCoord2d(1.0, 0.0);
332
+ glMultiTexCoord2d(GL_TEXTURE1, 1.0, 0.0);
333
+ glVertex2d(x + texture->width, y + texture->height); // BR
334
+ glEnd();
335
+
336
+ // Disable multitexturing.
337
+ if(!NIL_P(multitexture))
338
+ {
339
+ glBindTexture(GL_TEXTURE_2D, 0);
340
+ glActiveTexture(GL_TEXTURE0);
341
+ }
342
+
343
+ return Qnil;
344
+ }
345
+
346
+ // ----------------------------------------
347
+ VALUE Ashton_Texture_draw(int argc, VALUE argv[], VALUE self)
348
+ {
349
+ // TEXTURE(); // This isn't actually needed in this function.
350
+
351
+ VALUE x, y, z, options;
352
+ VALUE shader, blend_mode, color, multitexture, pixelated;
353
+
354
+ if(rb_scan_args(argc, argv, "31", &x, &y, &z, &options) == 4)
355
+ {
356
+ // Get :shader
357
+ shader = rb_hash_aref(options, SYMBOL("shader"));
358
+ if(!NIL_P(shader) && !rb_obj_is_kind_of(shader, rb_cShader))
359
+ {
360
+ rb_raise(rb_eTypeError, "Expected :shader option of type Ashton::Shader");
361
+ }
362
+
363
+ // Get draw :mode
364
+ blend_mode = rb_hash_aref(options, SYMBOL("mode"));
365
+ if(NIL_P(blend_mode))
366
+ {
367
+ blend_mode = SYMBOL(DRAW_MODE_ALPHA_BLEND);
368
+ }
369
+ else
370
+ {
371
+ Check_Type(blend_mode, T_SYMBOL);
372
+
373
+ ID blend_id = SYM2ID(blend_mode);
374
+ if(!(blend_id == rb_intern(DRAW_MODE_ALPHA_BLEND) ||
375
+ blend_id == rb_intern(DRAW_MODE_ADD) ||
376
+ blend_id == rb_intern(DRAW_MODE_MULTIPLY) ||
377
+ blend_id == rb_intern(DRAW_MODE_REPLACE)))
378
+ {
379
+ rb_raise(rb_eArgError, "Unsupported draw :mode, :%s", rb_id2name(blend_id));
380
+ }
381
+ }
382
+
383
+ // Get :color
384
+ color = rb_hash_aref(options, SYMBOL("color"));
385
+ if(NIL_P(color))
386
+ {
387
+ color = UINT2NUM(0xffffffff);
388
+ }
389
+ else if(!rb_obj_is_kind_of(color, rb_cColor))
390
+ {
391
+ rb_raise(rb_eTypeError, "Expecting :color to be a Gosu::Color");
392
+ }
393
+
394
+ // Get :multitexture
395
+ multitexture = rb_hash_aref(options, SYMBOL("multitexture"));
396
+ if(!NIL_P(multitexture) && !rb_obj_is_kind_of(multitexture, rb_cTexture))
397
+ {
398
+ rb_raise(rb_eTypeError, "Expected :multitexture option of type Ashton::Texture");
399
+ }
400
+
401
+ // Get :pixelated
402
+ pixelated = rb_hash_aref(options, SYMBOL("pixelated"));
403
+ if(NIL_P(pixelated))
404
+ {
405
+ pixelated = rb_funcall(rb_cTexture, rb_intern("pixelated?"), 0);
406
+ }
407
+ }
408
+ else
409
+ {
410
+ shader = multitexture = Qnil;
411
+ blend_mode = SYMBOL(DRAW_MODE_ALPHA_BLEND);
412
+ color = UINT2NUM(0xffffffff);
413
+ pixelated = rb_funcall(rb_cTexture, rb_intern("pixelated?"), 0);
414
+ }
415
+
416
+ // Enable the shader, if provided.
417
+ if(!NIL_P(shader)) rb_funcall(shader, rb_intern("enable"), 1, z);
418
+
419
+ // Create a GL block to do the actual drawing.
420
+ VALUE window = rb_gv_get("$window");
421
+
422
+ VALUE block_argv[1];
423
+ block_argv[0] = z;
424
+
425
+ VALUE parameters = rb_ary_new();
426
+ rb_ary_push(parameters, self);
427
+ rb_ary_push(parameters, x);
428
+ rb_ary_push(parameters, y);
429
+ rb_ary_push(parameters, blend_mode);
430
+ rb_ary_push(parameters, color);
431
+ rb_ary_push(parameters, shader);
432
+ rb_ary_push(parameters, multitexture);
433
+ rb_ary_push(parameters, pixelated);
434
+
435
+ rb_block_call(window, rb_intern("gl"), 1, block_argv,
436
+ RUBY_METHOD_FUNC(draw_block), parameters);
437
+
438
+ // Disable the shader, if provided.
439
+ if(!NIL_P(shader)) rb_funcall(shader, rb_intern("disable"), 1, z);
440
+
441
+ return Qnil;
442
+ }