ashton 0.0.1alpha → 0.0.2alpha

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/LICENSE +21 -21
  2. data/README.md +95 -68
  3. data/Rakefile +41 -23
  4. data/examples/bloom_example.rb +59 -0
  5. data/examples/lighting_example.rb +127 -0
  6. data/examples/media/SmallStar.png +0 -0
  7. data/examples/media/Starfighter.png +0 -0
  8. data/examples/media/simple.png +0 -0
  9. data/examples/noise_example.rb +94 -0
  10. data/examples/outline_example.rb +86 -0
  11. data/examples/particle_emitter_example.rb +114 -0
  12. data/examples/pixelate_example.rb +51 -49
  13. data/examples/pixelated_texture_example.rb +69 -0
  14. data/examples/radial_blur_example.rb +60 -62
  15. data/examples/shader_image_example.rb +74 -41
  16. data/examples/{shockwave2_example.rb → shockwave_example.rb} +74 -75
  17. data/examples/stencil_shader_example.rb +104 -0
  18. data/examples/{framebuffer_example.rb → texture_render_example.rb} +53 -49
  19. data/examples/{tv_screen_and_noise_example.rb → tv_screen_and_static_example.rb} +59 -59
  20. data/ext/ashton/GLee.c +18170 -0
  21. data/ext/ashton/GLee.h +17647 -0
  22. data/ext/ashton/ashton.c +42 -0
  23. data/ext/ashton/ashton.h +31 -0
  24. data/ext/ashton/color.c +45 -0
  25. data/ext/ashton/color.h +25 -0
  26. data/ext/ashton/common.h +41 -0
  27. data/ext/ashton/extconf.rb +42 -0
  28. data/ext/ashton/fast_math.c +30 -0
  29. data/ext/ashton/fast_math.h +30 -0
  30. data/ext/ashton/font.c +8 -0
  31. data/ext/ashton/font.h +16 -0
  32. data/ext/ashton/gosu.c +18 -0
  33. data/ext/ashton/gosu.h +19 -0
  34. data/ext/ashton/image.c +8 -0
  35. data/ext/ashton/image.h +16 -0
  36. data/ext/ashton/particle_emitter.c +788 -0
  37. data/ext/ashton/particle_emitter.h +171 -0
  38. data/ext/ashton/pixel_cache.c +237 -0
  39. data/ext/ashton/pixel_cache.h +58 -0
  40. data/ext/ashton/shader.c +9 -0
  41. data/ext/ashton/shader.h +16 -0
  42. data/ext/ashton/texture.c +442 -0
  43. data/ext/ashton/texture.h +63 -0
  44. data/ext/ashton/window.c +8 -0
  45. data/ext/ashton/window.h +16 -0
  46. data/lib/ashton.rb +38 -26
  47. data/lib/ashton/1.9/ashton.so +0 -0
  48. data/lib/ashton/gosu_ext/color.rb +24 -11
  49. data/lib/ashton/gosu_ext/font.rb +58 -0
  50. data/lib/ashton/gosu_ext/gosu_module.rb +16 -0
  51. data/lib/ashton/gosu_ext/image.rb +95 -31
  52. data/lib/ashton/gosu_ext/window.rb +78 -35
  53. data/lib/ashton/image_stub.rb +32 -36
  54. data/lib/ashton/lighting/light_source.rb +146 -0
  55. data/lib/ashton/lighting/manager.rb +98 -0
  56. data/lib/ashton/mixins/version_checking.rb +23 -0
  57. data/lib/ashton/particle_emitter.rb +87 -0
  58. data/lib/ashton/pixel_cache.rb +24 -0
  59. data/lib/ashton/shader.rb +353 -35
  60. data/lib/ashton/shaders/bloom.frag +41 -0
  61. data/lib/ashton/shaders/color_inversion.frag +11 -0
  62. data/lib/ashton/{post_process → shaders}/contrast.frag +16 -16
  63. data/lib/ashton/{shader → shaders}/default.frag +22 -19
  64. data/lib/ashton/{shader → shaders}/default.vert +13 -13
  65. data/lib/ashton/shaders/fade.frag +14 -0
  66. data/lib/ashton/shaders/grayscale.frag +15 -0
  67. data/lib/ashton/shaders/include/classicnoise2d.glsl +113 -0
  68. data/lib/ashton/shaders/include/classicnoise3d.glsl +177 -0
  69. data/lib/ashton/shaders/include/classicnoise4d.glsl +302 -0
  70. data/lib/ashton/{include/simplex.glsl → shaders/include/noise2d.glsl} +70 -63
  71. data/lib/ashton/shaders/include/noise3d.glsl +102 -0
  72. data/lib/ashton/shaders/include/noise4d.glsl +128 -0
  73. data/lib/ashton/shaders/include/rand.glsl +5 -0
  74. data/lib/ashton/shaders/lighting/distort.frag +57 -0
  75. data/lib/ashton/shaders/lighting/draw_shadows.frag +60 -0
  76. data/lib/ashton/shaders/lighting/shadow_blur.frag +60 -0
  77. data/lib/ashton/shaders/mezzotint.frag +22 -0
  78. data/lib/ashton/shaders/multitexture2.vert +19 -0
  79. data/lib/ashton/shaders/outline.frag +45 -0
  80. data/lib/ashton/{post_process → shaders}/pixelate.frag +48 -48
  81. data/lib/ashton/shaders/radial_blur.frag +63 -0
  82. data/lib/ashton/shaders/sepia.frag +26 -0
  83. data/lib/ashton/{post_process/shockwave2.frag → shaders/shockwave.frag} +38 -35
  84. data/lib/ashton/shaders/signed_distance_field.frag +80 -0
  85. data/lib/ashton/{post_process/noise.frag → shaders/static.frag} +25 -27
  86. data/lib/ashton/shaders/stencil.frag +27 -0
  87. data/lib/ashton/shaders/tv_screen.frag +23 -0
  88. data/lib/ashton/signed_distance_field.rb +151 -0
  89. data/lib/ashton/texture.rb +186 -0
  90. data/lib/ashton/version.rb +2 -2
  91. data/lib/ashton/window_buffer.rb +16 -0
  92. data/spec/ashton/ashton_spec.rb +22 -0
  93. data/spec/ashton/gosu_ext/color_spec.rb +34 -0
  94. data/spec/ashton/gosu_ext/font_spec.rb +57 -0
  95. data/spec/ashton/gosu_ext/gosu_spec.rb +11 -0
  96. data/spec/ashton/gosu_ext/image_spec.rb +66 -0
  97. data/spec/ashton/gosu_ext/window_spec.rb +71 -0
  98. data/spec/ashton/image_stub_spec.rb +46 -0
  99. data/spec/ashton/particle_emitter_spec.rb +123 -0
  100. data/spec/ashton/pixel_cache_spec.rb +153 -0
  101. data/spec/ashton/shader_spec.rb +152 -0
  102. data/spec/ashton/signed_distance_field_spec.rb +163 -0
  103. data/spec/ashton/texture_spec.rb +347 -0
  104. data/spec/helper.rb +12 -0
  105. metadata +159 -28
  106. data/examples/output/README.txt +0 -1
  107. data/lib/ashton/base_shader.rb +0 -172
  108. data/lib/ashton/framebuffer.rb +0 -183
  109. data/lib/ashton/post_process.rb +0 -83
  110. data/lib/ashton/post_process/default.vert +0 -9
  111. data/lib/ashton/post_process/fade.frag +0 -11
  112. data/lib/ashton/post_process/mezzotint.frag +0 -24
  113. data/lib/ashton/post_process/radial_blur.frag +0 -31
  114. data/lib/ashton/post_process/sepia.frag +0 -19
  115. data/lib/ashton/post_process/shockwave.frag +0 -40
  116. data/lib/ashton/post_process/tv_screen.frag +0 -32
@@ -1,63 +1,61 @@
1
- # Use of GLSL shader in Gosu to post-process the entire screen.
2
-
3
- begin
4
- require 'rubygems'
5
- rescue LoadError
6
- end
7
-
8
- $LOAD_PATH.unshift File.expand_path('../lib/', File.dirname(__FILE__))
9
- require "ashton"
10
-
11
- def shader(file); File.read File.expand_path("../lib/ashton/post_process/#{file}", File.dirname(__FILE__)) end
12
-
13
- class TestWindow < Gosu::Window
14
- def initialize
15
- super 640, 480, false
16
- self.caption = "Post-processing with 'radial_blur' - hold space to disable; 1..9 sets blurriness"
17
-
18
- @blur = Ashton::PostProcess.new shader('radial_blur.frag')
19
- @blur['in_BrightFactor'] = 1.5
20
- @blur['in_BlurFactor'] = @blur_factor = 2.0
21
- @blur['in_Passes'] = 20 # Quite a lot of work, but just proves how fast shader are!
22
- @font = Gosu::Font.new self, Gosu::default_font_name, 40
23
-
24
- update # Ensure the values are initially set.
25
- end
26
-
27
- def update
28
- # Wiggle the blur about a bit each frame!
29
- @blur['in_OriginX'] = mouse_x
30
- @blur['in_OriginY'] = mouse_y
31
- end
32
-
33
- def button_down(id)
34
- if (Gosu::Kb1..Gosu::Kb9).include? id
35
- @blur_factor = (id - Gosu::Kb1 + 1).to_f
36
- @blur['in_BlurFactor'] = @blur_factor
37
- elsif id == Gosu::KbEscape
38
- close
39
- end
40
- end
41
-
42
- def draw_scene
43
- @font.draw_rel "Hello world!", 100, 100, 0, 0, 0.5, 0.5
44
- @font.draw_rel "Goodbye world!", 400, 280, 0, 0.5, 0.5
45
-
46
- @font.draw_rel "X", mouse_x, mouse_y, 0, 0.5, 0.5
47
- end
48
-
49
- def draw
50
- if button_down? Gosu::KbSpace
51
- draw_scene
52
- else
53
- post_process @blur do
54
- draw_scene
55
- end
56
- end
57
-
58
- # Drawing after the effect isn't processed, which is useful for GUI elements.
59
- @font.draw "Blur Factor: #{@blur_factor}", 0, 0, 0
60
- end
61
- end
62
-
1
+ # Use of GLSL shader in Gosu to post-process the entire screen.
2
+
3
+ begin
4
+ require 'rubygems'
5
+ rescue LoadError
6
+ end
7
+
8
+ $LOAD_PATH.unshift File.expand_path('../lib/', File.dirname(__FILE__))
9
+ require "ashton"
10
+
11
+ def media_path(file); File.expand_path "media/#{file}", File.dirname(__FILE__) end
12
+
13
+ class TestWindow < Gosu::Window
14
+ def initialize
15
+ super 640, 480, false
16
+ self.caption = "Post-processing with 'radial_blur' - mouse pos affects spacing/strength"
17
+
18
+ @blur = Ashton::Shader.new fragment: :radial_blur
19
+ @font = Gosu::Font.new self, Gosu::default_font_name, 40
20
+ @background = Gosu::Image.new(self, media_path("Earth.png"), true)
21
+
22
+ update # Ensure the values are initially set.
23
+ end
24
+
25
+ def update
26
+ $gosu_blocks.clear if defined? $gosu_blocks # Workaround for Gosu bug (0.7.45)
27
+
28
+ @blur.spacing = [2.0 * mouse_x / width, 0.0].max
29
+ @blur.strength = [4.4 * mouse_y / height, 0.0].max
30
+ end
31
+
32
+ def needs_cursor?; true end
33
+
34
+ def button_down(id)
35
+ if (Gosu::Kb1..Gosu::Kb9).include? id
36
+ @blur_factor = (id - Gosu::Kb1 + 1).to_f
37
+ @blur.blur_factor = @blur_factor
38
+ elsif id == Gosu::KbEscape
39
+ close
40
+ end
41
+ end
42
+
43
+ def draw
44
+ shaders = button_down?(Gosu::KbSpace) ? [] : [@blur]
45
+ post_process(*shaders) do
46
+ @background.draw 0, 0, 0, width.fdiv(@background.width), height.fdiv(@background.height)
47
+
48
+ @font.draw_rel "Hello world!", 100, 100, 0, 0.5, 0.5, 1, 1, Gosu::Color::RED
49
+ @font.draw_rel "Goodbye world!", 400, 280, 0, 0.5, 0.5, 1, 1, Gosu::Color::BLUE
50
+ end
51
+
52
+ # Drawing after the effect isn't processed, which is useful for GUI elements.
53
+ @font.draw_rel "Less spacing", 0, height / 2, 0, 0, 0.5
54
+ @font.draw_rel "More spacing", width, height / 2, 0, 1, 0.5
55
+
56
+ @font.draw_rel "Less strength", width / 2, 0, 0, 0.5, 0
57
+ @font.draw_rel "More strength", width / 2, height, 0, 0.5, 1
58
+ end
59
+ end
60
+
63
61
  TestWindow.new.show
@@ -1,42 +1,75 @@
1
- # Use of GLSL shader in Gosu.
2
-
3
- begin
4
- require 'rubygems'
5
- rescue LoadError
6
- end
7
-
8
- $LOAD_PATH.unshift File.expand_path('../lib/', File.dirname(__FILE__))
9
- require "ashton"
10
-
11
- def media_path(file); File.expand_path "media/#{file}", File.dirname(__FILE__) end
12
- def output_path(file); File.expand_path "output/#{file}", File.dirname(__FILE__) end
13
-
14
- class GameWindow < Gosu::Window
15
- def initialize
16
- super 640, 480, false
17
- self.caption = "Gosu & OpenGL Integration Demo (SHADERS)"
18
-
19
- @font = Gosu::Font.new self, Gosu::default_font_name, 20
20
- @image = Gosu::Image.new self, media_path("Earth.png"), true
21
- @shader = Ashton::Shader.new # Just use default shader for now.
22
- end
23
-
24
- def draw
25
- # draw, with and without colour.
26
- @image.draw 10, 10, 0, :shader => @shader
27
- @image.draw 10, @image.height + 20, 0, 1, 1, Gosu::Color::RED, :shader => @shader
28
-
29
- # draw#rot, with and without colour.
30
- @image.draw_rot 280, 0, 0, 10, 0, 0, :shader => @shader
31
- @image.draw_rot 280, @image.height + 10, 0, 10, 0, 0, 1, 1, Gosu::Color::RED, :shader => @shader
32
- end
33
-
34
- def button_down(id)
35
- if id == Gosu::KbEscape
36
- close
37
- end
38
- end
39
- end
40
-
41
- window = GameWindow.new
1
+ # Use of GLSL shader in Gosu.
2
+
3
+ begin
4
+ require 'rubygems'
5
+ rescue LoadError
6
+ end
7
+
8
+ $LOAD_PATH.unshift File.expand_path('../lib/', File.dirname(__FILE__))
9
+ require "ashton"
10
+
11
+ def media_path(file); File.expand_path "media/#{file}", File.dirname(__FILE__) end
12
+ def output_path(file); File.expand_path "output/#{file}", File.dirname(__FILE__) end
13
+
14
+ class GameWindow < Gosu::Window
15
+ def initialize
16
+ super 640, 480, false
17
+ self.caption = "Gosu & OpenGL Integration Demo (SHADERS)"
18
+
19
+ @font = Gosu::Font.new self, Gosu::default_font_name, 24
20
+ @image = Gosu::Image.new self, media_path("Earth.png"), true
21
+
22
+ @sepia = Ashton::Shader.new fragment: :sepia
23
+ @contrast = Ashton::Shader.new fragment: :contrast
24
+ @mezzotint = Ashton::Shader.new fragment: :mezzotint
25
+ @grayscale = Ashton::Shader.new fragment: :grayscale
26
+ @color_inversion = Ashton::Shader.new fragment: :color_inversion
27
+ @fade = Ashton::Shader.new fragment: :fade, uniforms: {
28
+ fade: 0.75,
29
+ }
30
+
31
+ update # Ensure values are set before draw.
32
+ end
33
+
34
+ def update
35
+ $gosu_blocks.clear if defined? $gosu_blocks # workaround for Gosu 0.7.45 bug.
36
+
37
+ @fade.fade = @fade_fade = Math::sin(Gosu::milliseconds / 1000.0) / 2 + 0.5
38
+ @contrast.contrast = @contrast_contrast = Math::sin(Gosu::milliseconds / 1000.0) * 2 + 2
39
+ @mezzotint.t = (Gosu::milliseconds / 100.0).to_i
40
+ end
41
+
42
+ def draw
43
+ @image.draw 0, 0, 0, width.fdiv(@image.width), height.fdiv(@image.height)
44
+
45
+ # draw, with and without colour.
46
+ @image.draw 10, 10, 0, :shader => @sepia
47
+ @font.draw ":sepia", 10, 150, 0
48
+
49
+ @image.draw 10, @image.height + 120, 0, 1, 1, Gosu::Color::RED, :shader => @mezzotint
50
+ @font.draw ":mezzotint", 10, 400, 0
51
+
52
+ # draw_rot, with and without colour.
53
+ @image.draw_rot 235, 0, 0, 10, 0, 0, :shader => @contrast
54
+ @font.draw ":contrast #{"%.2f" % @contrast_contrast}", 235, 150, 0
55
+
56
+ @image.draw_rot 235, @image.height + 110, 0, 10, 0, 0, 1, 1, Gosu::Color::RED, :shader => @fade
57
+ @font.draw ":fade #{"%.2f" % @fade_fade}", 235, 400, 0
58
+
59
+ # More draws.
60
+ @image.draw 430, 10, 0, :shader => @grayscale
61
+ @font.draw ":grayscale", 430, 150, 0
62
+
63
+ @image.draw 430, @image.height + 110, 0, :shader => @color_inversion
64
+ @font.draw ":color_inversion", 430, 400, 0
65
+ end
66
+
67
+ def button_down(id)
68
+ if id == Gosu::KbEscape
69
+ close
70
+ end
71
+ end
72
+ end
73
+
74
+ window = GameWindow.new
42
75
  window.show
@@ -1,76 +1,75 @@
1
- # Use of GLSL shader in Gosu to post-process the entire screen.
2
-
3
- begin
4
- require 'rubygems'
5
- rescue LoadError
6
- end
7
-
8
- $LOAD_PATH.unshift File.expand_path('../lib/', File.dirname(__FILE__))
9
- require "ashton"
10
-
11
- def shader(file); File.read File.expand_path("../lib/ashton/post_process/#{file}", File.dirname(__FILE__)) end
12
- def media_path(file); File.expand_path "media/#{file}", File.dirname(__FILE__) end
13
-
14
- class Shockwave
15
- def age; Gosu::milliseconds - @start_time; end
16
-
17
- def process
18
- @shader.process
19
- end
20
-
21
- def initialize(x, y)
22
- @shader = Ashton::PostProcess.new shader('shockwave2.frag')
23
- @shader['in_ShockParams'] = [10.0, 0.8, 0.1]
24
- @shader['in_Center'] = [x, $window.height - y]
25
- @start_time = Gosu::milliseconds
26
- end
27
-
28
- def update
29
- @shader['in_Time'] = age / 1000.0
30
- end
31
- end
32
-
33
- class TestWindow < Gosu::Window
34
- def initialize
35
- super 640, 480, false
36
- self.caption = "Post-processing with 'shockwave2.frag' - Click on window to create a splash"
37
-
38
- @font = Gosu::Font.new self, Gosu::default_font_name, 40
39
- @background = Gosu::Image.new(self, media_path("Earth.png"), true)
40
- @waves = []
41
- end
42
-
43
- def update
44
- @waves.each {|w| w.update }
45
- @waves.delete_if {|w| w.age > 3000 }
46
- end
47
-
48
- def needs_cursor?
49
- true
50
- end
51
-
52
- def button_down(id)
53
- case id
54
- when Gosu::MsLeft
55
- @waves << Shockwave.new(mouse_x, mouse_y)
56
- when Gosu::KbEscape
57
- close
58
- end
59
- end
60
-
61
- def draw
62
- @background.draw 0, 0, 0, width.fdiv(@background.width), height.fdiv(@background.height)
63
- @font.draw_rel "Hello world!", 350, 50, 0, 0.5, 0.5
64
- @font.draw_rel "Goodbye world!", 400, 350, 0, 0.5, 0.5
65
-
66
- # Since we want to process multiple post-processing effects...
67
- @waves.each do |wave|
68
- wave.process
69
- end
70
-
71
- # Drawing after the effect isn't processed, which is useful for GUI elements.
72
- @font.draw "FPS: #{Gosu::fps} Waves: #{@waves.size}", 0, 0, 0
73
- end
74
- end
75
-
1
+ # Use of GLSL shader in Gosu to post-process the entire screen.
2
+
3
+ begin
4
+ require 'rubygems'
5
+ rescue LoadError
6
+ end
7
+
8
+ $LOAD_PATH.unshift File.expand_path('../lib/', File.dirname(__FILE__))
9
+ require "ashton"
10
+
11
+ def media_path(file); File.expand_path "media/#{file}", File.dirname(__FILE__) end
12
+
13
+ class Shockwave
14
+ attr_reader :shader
15
+
16
+ def age; (Gosu::milliseconds - @start_time) / 1000.0; end
17
+ def dead?; age > 3.0 end
18
+
19
+ def initialize(x, y)
20
+ @shader = Ashton::Shader.new fragment: :shockwave, uniforms: {
21
+ shock_params: [10.0, 0.8, 0.1], # Not entirely sure what these represent!
22
+ center: [x, y],
23
+ }
24
+ @start_time = Gosu::milliseconds
25
+ end
26
+
27
+ def update
28
+ @shader.time = age
29
+ end
30
+ end
31
+
32
+ class TestWindow < Gosu::Window
33
+ def initialize
34
+ super 640, 480, false
35
+ self.caption = "Post-processing with 'shockwave2.frag' - Click on window to create a splash!"
36
+
37
+ @font = Gosu::Font.new self, Gosu::default_font_name, 40
38
+ @background = Gosu::Image.new(self, media_path("Earth.png"), true)
39
+ @waves = []
40
+ end
41
+
42
+ def update
43
+ $gosu_blocks.clear if defined? $gosu_blocks # Workaround for Gosu bug (0.7.45)
44
+
45
+ @waves.delete_if {|w| w.dead? }
46
+ @waves.each {|w| w.update }
47
+ end
48
+
49
+ def needs_cursor?
50
+ true
51
+ end
52
+
53
+ def button_down(id)
54
+ case id
55
+ when Gosu::MsLeft
56
+ @waves << Shockwave.new(mouse_x, mouse_y)
57
+ when Gosu::KbEscape
58
+ close
59
+ end
60
+ end
61
+
62
+ def draw
63
+ shaders = @waves.map {|w| w.shader }
64
+ post_process(*shaders) do
65
+ @background.draw 0, 0, 0, width.fdiv(@background.width), height.fdiv(@background.height)
66
+ @font.draw_rel "Hello world!", 350, 50, 0, 0.5, 0.5
67
+ @font.draw_rel "Goodbye world!", 400, 350, 0, 0.5, 0.5
68
+ end
69
+
70
+ # Drawing after the effect isn't processed, which is useful for GUI elements.
71
+ @font.draw "FPS: #{Gosu::fps} Waves: #{@waves.size}", 0, 0, 0
72
+ end
73
+ end
74
+
76
75
  TestWindow.new.show
@@ -0,0 +1,104 @@
1
+ # Use of a stencil shader and multitexturing in Gosu.
2
+
3
+ begin
4
+ require 'rubygems'
5
+ rescue LoadError
6
+ end
7
+
8
+ $LOAD_PATH.unshift File.expand_path('../lib/', File.dirname(__FILE__))
9
+ require "ashton"
10
+
11
+ def media_path(file); File.expand_path "media/#{file}", File.dirname(__FILE__) end
12
+ def output_path(file); File.expand_path "output/#{file}", File.dirname(__FILE__) end
13
+
14
+ class GameWindow < Gosu::Window
15
+ def initialize
16
+ super 640, 480, false
17
+ self.caption = "Stencil shader - <space> new stencil layout <I> to invert stencilling effect"
18
+
19
+ setup_example_objects
20
+
21
+ @image = Gosu::Image.new self, media_path("LargeStar.png"), false
22
+ @stencil = Gosu::Image.new self, media_path("SmallStar.png"), false
23
+
24
+ # The texture to draw the stencil on. It's best to use an
25
+ # Ashton::WindowBuffer, since it is the same size as the window itself.
26
+ @stencil_texture = Ashton::WindowBuffer.new
27
+
28
+ # Fill the stencil texture
29
+ place_stencils
30
+
31
+ @shader = Ashton::Shader.new vertex: :multitexture2, fragment: :stencil
32
+ @inverted = false
33
+ end
34
+
35
+ def draw
36
+ # Draw the background and ship
37
+ draw_example_objects
38
+
39
+
40
+ # We'll use the window's primary buffer to draw our images that need to be masked.
41
+ # We can use this buffer as long as we don't expect it to be cleared before we use it
42
+ # or unaltered between our uses of it.
43
+ primary_buffer.render do |buffer|
44
+ buffer.clear
45
+ @image.draw_rot(@image.width / 2, @image.height / 2, 0, @rotation)
46
+ end
47
+
48
+ # Draw the primary buffer with our shader and give it our stencil to work with.
49
+ primary_buffer.draw 0, 0, 0, shader: @shader, multitexture: @stencil_texture
50
+
51
+ @font.draw "Stencil effect #{"(INVERTED)" if @inverted}", 0, 0, 0
52
+
53
+ # Show the stencil texture drawn directly on the screen, for comparison.
54
+ @stencil_texture.draw 320, 0, 0, mode: :replace
55
+ @font.draw "Stencil texture (black is transparent)", 320, 0, 0
56
+ end
57
+
58
+ # Clear the stencil texture and draw new stencils on top of it
59
+ def place_stencils
60
+ @stencil_texture.render do |texture|
61
+ texture.clear
62
+ 5.times do
63
+ @stencil.draw_rot(rand(@image.width), rand(@image.height), 1, 0, 0.5, 0.5, 2, 2)
64
+ end
65
+ end
66
+ end
67
+
68
+ # Not important --------
69
+
70
+ def update
71
+ $gosu_blocks.clear if defined? $gosu_blocks # Workaround for Gosu bug (0.7.45)
72
+ @rotation = (@rotation + 1) % 360
73
+ end
74
+
75
+ def button_down(id)
76
+ case id
77
+ when Gosu::KbEscape
78
+ close
79
+
80
+ when Gosu::KbSpace
81
+ place_stencils
82
+
83
+ when Gosu::KbI
84
+ @inverted = !@inverted
85
+ @shader.inverted = @inverted
86
+ end
87
+ end
88
+
89
+ private
90
+ def draw_example_objects
91
+ @background.draw 0, 0, 0, width.fdiv(@background.width), height.fdiv(@background.height)
92
+ @ship.draw(100, 200 + 200 * Math.sin(@rotation.gosu_to_radians), 0)
93
+ end
94
+
95
+ def setup_example_objects
96
+ @font = Gosu::Font.new $window, Gosu::default_font_name, 20
97
+ @background = Gosu::Image.new self, media_path("Earth.png"), true
98
+ @ship = Gosu::Image.new self, media_path("Starfighter.bmp"), false
99
+ @rotation = 0
100
+ end
101
+ end
102
+
103
+ window = GameWindow.new
104
+ window.show