ashton 0.0.1alpha → 0.0.2alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +21 -21
- data/README.md +95 -68
- data/Rakefile +41 -23
- data/examples/bloom_example.rb +59 -0
- data/examples/lighting_example.rb +127 -0
- data/examples/media/SmallStar.png +0 -0
- data/examples/media/Starfighter.png +0 -0
- data/examples/media/simple.png +0 -0
- data/examples/noise_example.rb +94 -0
- data/examples/outline_example.rb +86 -0
- data/examples/particle_emitter_example.rb +114 -0
- data/examples/pixelate_example.rb +51 -49
- data/examples/pixelated_texture_example.rb +69 -0
- data/examples/radial_blur_example.rb +60 -62
- data/examples/shader_image_example.rb +74 -41
- data/examples/{shockwave2_example.rb → shockwave_example.rb} +74 -75
- data/examples/stencil_shader_example.rb +104 -0
- data/examples/{framebuffer_example.rb → texture_render_example.rb} +53 -49
- data/examples/{tv_screen_and_noise_example.rb → tv_screen_and_static_example.rb} +59 -59
- data/ext/ashton/GLee.c +18170 -0
- data/ext/ashton/GLee.h +17647 -0
- data/ext/ashton/ashton.c +42 -0
- data/ext/ashton/ashton.h +31 -0
- data/ext/ashton/color.c +45 -0
- data/ext/ashton/color.h +25 -0
- data/ext/ashton/common.h +41 -0
- data/ext/ashton/extconf.rb +42 -0
- data/ext/ashton/fast_math.c +30 -0
- data/ext/ashton/fast_math.h +30 -0
- data/ext/ashton/font.c +8 -0
- data/ext/ashton/font.h +16 -0
- data/ext/ashton/gosu.c +18 -0
- data/ext/ashton/gosu.h +19 -0
- data/ext/ashton/image.c +8 -0
- data/ext/ashton/image.h +16 -0
- data/ext/ashton/particle_emitter.c +788 -0
- data/ext/ashton/particle_emitter.h +171 -0
- data/ext/ashton/pixel_cache.c +237 -0
- data/ext/ashton/pixel_cache.h +58 -0
- data/ext/ashton/shader.c +9 -0
- data/ext/ashton/shader.h +16 -0
- data/ext/ashton/texture.c +442 -0
- data/ext/ashton/texture.h +63 -0
- data/ext/ashton/window.c +8 -0
- data/ext/ashton/window.h +16 -0
- data/lib/ashton.rb +38 -26
- data/lib/ashton/1.9/ashton.so +0 -0
- data/lib/ashton/gosu_ext/color.rb +24 -11
- data/lib/ashton/gosu_ext/font.rb +58 -0
- data/lib/ashton/gosu_ext/gosu_module.rb +16 -0
- data/lib/ashton/gosu_ext/image.rb +95 -31
- data/lib/ashton/gosu_ext/window.rb +78 -35
- data/lib/ashton/image_stub.rb +32 -36
- data/lib/ashton/lighting/light_source.rb +146 -0
- data/lib/ashton/lighting/manager.rb +98 -0
- data/lib/ashton/mixins/version_checking.rb +23 -0
- data/lib/ashton/particle_emitter.rb +87 -0
- data/lib/ashton/pixel_cache.rb +24 -0
- data/lib/ashton/shader.rb +353 -35
- data/lib/ashton/shaders/bloom.frag +41 -0
- data/lib/ashton/shaders/color_inversion.frag +11 -0
- data/lib/ashton/{post_process → shaders}/contrast.frag +16 -16
- data/lib/ashton/{shader → shaders}/default.frag +22 -19
- data/lib/ashton/{shader → shaders}/default.vert +13 -13
- data/lib/ashton/shaders/fade.frag +14 -0
- data/lib/ashton/shaders/grayscale.frag +15 -0
- data/lib/ashton/shaders/include/classicnoise2d.glsl +113 -0
- data/lib/ashton/shaders/include/classicnoise3d.glsl +177 -0
- data/lib/ashton/shaders/include/classicnoise4d.glsl +302 -0
- data/lib/ashton/{include/simplex.glsl → shaders/include/noise2d.glsl} +70 -63
- data/lib/ashton/shaders/include/noise3d.glsl +102 -0
- data/lib/ashton/shaders/include/noise4d.glsl +128 -0
- data/lib/ashton/shaders/include/rand.glsl +5 -0
- data/lib/ashton/shaders/lighting/distort.frag +57 -0
- data/lib/ashton/shaders/lighting/draw_shadows.frag +60 -0
- data/lib/ashton/shaders/lighting/shadow_blur.frag +60 -0
- data/lib/ashton/shaders/mezzotint.frag +22 -0
- data/lib/ashton/shaders/multitexture2.vert +19 -0
- data/lib/ashton/shaders/outline.frag +45 -0
- data/lib/ashton/{post_process → shaders}/pixelate.frag +48 -48
- data/lib/ashton/shaders/radial_blur.frag +63 -0
- data/lib/ashton/shaders/sepia.frag +26 -0
- data/lib/ashton/{post_process/shockwave2.frag → shaders/shockwave.frag} +38 -35
- data/lib/ashton/shaders/signed_distance_field.frag +80 -0
- data/lib/ashton/{post_process/noise.frag → shaders/static.frag} +25 -27
- data/lib/ashton/shaders/stencil.frag +27 -0
- data/lib/ashton/shaders/tv_screen.frag +23 -0
- data/lib/ashton/signed_distance_field.rb +151 -0
- data/lib/ashton/texture.rb +186 -0
- data/lib/ashton/version.rb +2 -2
- data/lib/ashton/window_buffer.rb +16 -0
- data/spec/ashton/ashton_spec.rb +22 -0
- data/spec/ashton/gosu_ext/color_spec.rb +34 -0
- data/spec/ashton/gosu_ext/font_spec.rb +57 -0
- data/spec/ashton/gosu_ext/gosu_spec.rb +11 -0
- data/spec/ashton/gosu_ext/image_spec.rb +66 -0
- data/spec/ashton/gosu_ext/window_spec.rb +71 -0
- data/spec/ashton/image_stub_spec.rb +46 -0
- data/spec/ashton/particle_emitter_spec.rb +123 -0
- data/spec/ashton/pixel_cache_spec.rb +153 -0
- data/spec/ashton/shader_spec.rb +152 -0
- data/spec/ashton/signed_distance_field_spec.rb +163 -0
- data/spec/ashton/texture_spec.rb +347 -0
- data/spec/helper.rb +12 -0
- metadata +159 -28
- data/examples/output/README.txt +0 -1
- data/lib/ashton/base_shader.rb +0 -172
- data/lib/ashton/framebuffer.rb +0 -183
- data/lib/ashton/post_process.rb +0 -83
- data/lib/ashton/post_process/default.vert +0 -9
- data/lib/ashton/post_process/fade.frag +0 -11
- data/lib/ashton/post_process/mezzotint.frag +0 -24
- data/lib/ashton/post_process/radial_blur.frag +0 -31
- data/lib/ashton/post_process/sepia.frag +0 -19
- data/lib/ashton/post_process/shockwave.frag +0 -40
- data/lib/ashton/post_process/tv_screen.frag +0 -32
data/lib/ashton/shader.rb
CHANGED
|
@@ -1,62 +1,380 @@
|
|
|
1
|
-
require "ashton/base_shader"
|
|
2
|
-
|
|
3
1
|
module Ashton
|
|
4
|
-
class Shader
|
|
5
|
-
|
|
2
|
+
class Shader
|
|
3
|
+
include Mixins::VersionChecking
|
|
4
|
+
|
|
5
|
+
INVALID_LOCATION = -1
|
|
6
|
+
MIN_OPENGL_VERSION = 2.0 # For GLSL 1.10
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
INCLUDE_PATH = File.expand_path "../shaders/include", __FILE__
|
|
9
|
+
BUILT_IN_SHADER_PATH = File.expand_path "../shaders", __FILE__
|
|
10
|
+
FRAGMENT_EXTENSION = ".frag"
|
|
11
|
+
VERTEX_EXTENSION = ".vert"
|
|
12
|
+
|
|
13
|
+
# List of built-in functions.
|
|
14
|
+
BUILT_IN_FUNCTIONS = Dir[File.join(INCLUDE_PATH, "*.glsl")].map do |filename|
|
|
15
|
+
filename =~ /(\w+)\.glsl/
|
|
16
|
+
$1.to_sym
|
|
17
|
+
end
|
|
10
18
|
|
|
11
|
-
|
|
19
|
+
attr_reader :vertex_source, :fragment_source
|
|
20
|
+
|
|
21
|
+
# Is the shader currently in use?
|
|
22
|
+
def enabled?; !!@previous_program end
|
|
23
|
+
# Is this the currently activated shader program?
|
|
24
|
+
def current?; glGetIntegerv(GL_CURRENT_PROGRAM) == @program end
|
|
25
|
+
|
|
26
|
+
# Instead of passing in source code, a file-name will be loaded or use a symbol to choose a built-in shader.
|
|
27
|
+
#
|
|
28
|
+
# `#include` will be recursively replaced in the source.
|
|
12
29
|
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
# @option options [String] :
|
|
30
|
+
# * `#include <noise>` will load the built-in shader function, shaders/include/noise.glsl
|
|
31
|
+
# * `#include "/home/spooner/noise.glsl"` will include that file, relative to the current working directory, NOT the source file.
|
|
32
|
+
#
|
|
33
|
+
# @option options :vertex [String, Symbol] (:default) Source code for vertex shader.
|
|
34
|
+
# @option options :vert [String, Symbol] (:default) Equivalent to :vertex
|
|
35
|
+
# @option options :fragment [String, Symbol] (:default) Source code for fragment shader.
|
|
36
|
+
# @option options :frag [String, Symbol] (:default) Equivalent to :fragment
|
|
37
|
+
# @option options :uniforms [Hash] Sets uniforms, as though calling shader[key] = value for each entry (but faster).
|
|
17
38
|
def initialize(options = {})
|
|
18
|
-
|
|
39
|
+
check_opengl_version MIN_OPENGL_VERSION
|
|
19
40
|
|
|
20
|
-
|
|
21
|
-
|
|
41
|
+
vertex = options[:vertex] || options[:vert] || :default
|
|
42
|
+
fragment = options[:fragment] || options[:frag] || :default
|
|
22
43
|
|
|
23
|
-
|
|
24
|
-
|
|
44
|
+
@vertex_source = process_source vertex, VERTEX_EXTENSION
|
|
45
|
+
@fragment_source = process_source fragment, FRAGMENT_EXTENSION
|
|
25
46
|
|
|
47
|
+
@uniform_locations = {}
|
|
48
|
+
@attribute_locations = {}
|
|
49
|
+
@program = nil
|
|
50
|
+
@image = nil
|
|
26
51
|
@color = [1, 1, 1, 1]
|
|
52
|
+
|
|
53
|
+
# Actually compile and link.
|
|
54
|
+
@vertex = compile GL_VERTEX_SHADER, @vertex_source
|
|
55
|
+
@fragment = compile GL_FRAGMENT_SHADER, @fragment_source
|
|
56
|
+
link
|
|
57
|
+
|
|
58
|
+
# In case we are using '#version 130' or higher, set out own color output.
|
|
59
|
+
begin
|
|
60
|
+
glBindFragDataLocationEXT @program, 0, "out_FragColor"
|
|
61
|
+
rescue NotImplementedError
|
|
62
|
+
# Might fail on an old system, but they will be fine just running GLSL 1.10 or 1.20
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
enable do
|
|
66
|
+
# GL_TEXTURE0 will be activated later. This is the main image texture.
|
|
67
|
+
set_uniform uniform_location("in_Texture", required: false), 0
|
|
68
|
+
|
|
69
|
+
# For multi-textured shaders, we use in_Texture<NUM> instead.
|
|
70
|
+
set_uniform uniform_location("in_Texture0", required: false), 0
|
|
71
|
+
set_uniform uniform_location("in_Texture1", required: false), 1
|
|
72
|
+
|
|
73
|
+
# These are optional, and can be used to check pixel size.
|
|
74
|
+
set_uniform uniform_location("in_WindowWidth", required: false), $window.width
|
|
75
|
+
set_uniform uniform_location("in_WindowHeight", required: false), $window.height
|
|
76
|
+
|
|
77
|
+
# Set uniform values with :uniforms hash.
|
|
78
|
+
if options.has_key? :uniforms
|
|
79
|
+
options[:uniforms].each_pair do |uniform, value|
|
|
80
|
+
self[uniform] = value
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
27
84
|
end
|
|
28
85
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
86
|
+
protected
|
|
87
|
+
# Converts :frog_head to "in_FrogHead"
|
|
88
|
+
def uniform_name_from_symbol(uniform)
|
|
89
|
+
"in_#{uniform.to_s.split("_").map(&:capitalize).join}"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
public
|
|
93
|
+
# Creates a copy of the shader program, recompiling the source,
|
|
94
|
+
# but not preserving the uniform values.
|
|
95
|
+
def dup
|
|
96
|
+
self.class.new :vertex => @vertex_source, :fragment => @fragment_source
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
public
|
|
100
|
+
# Make this the current shader program. Use with a block or, alternatively, use #enable and #disable separately.
|
|
101
|
+
def enable(z = nil)
|
|
102
|
+
$window.gl z do
|
|
103
|
+
raise ShaderError, "This shader already enabled." if enabled?
|
|
104
|
+
current_shader = glGetIntegerv GL_CURRENT_PROGRAM
|
|
105
|
+
raise ShaderError, "Another shader already enabled." if current_shader > 0
|
|
106
|
+
|
|
107
|
+
@previous_program = current_shader
|
|
108
|
+
glUseProgram @program
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
result = nil
|
|
112
|
+
|
|
113
|
+
if block_given?
|
|
114
|
+
begin
|
|
115
|
+
result = yield self
|
|
116
|
+
ensure
|
|
117
|
+
disable z
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
result
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Disable the shader program. Only required if using #enable without a block.
|
|
125
|
+
def disable(z = nil)
|
|
126
|
+
$window.gl z do
|
|
127
|
+
raise ShaderError, "Shader not enabled." unless enabled?
|
|
128
|
+
glUseProgram @previous_program # Disable the shader!
|
|
129
|
+
@previous_program = nil
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
nil
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
public
|
|
136
|
+
# Allow
|
|
137
|
+
# `shader.blob_frequency = 5`
|
|
138
|
+
# to map to
|
|
139
|
+
# `shader["in_BlobFrequency"] = 5`
|
|
140
|
+
# TODO: define specific methods at compile time, based on parsing the source?
|
|
141
|
+
def method_missing(meth, *args, &block)
|
|
142
|
+
if args.size == 1 and meth =~ /^(.+)=$/
|
|
143
|
+
self[$1.to_sym] = args[0]
|
|
144
|
+
else
|
|
145
|
+
super meth, *args, &block
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
public
|
|
150
|
+
# Set the value of a uniform.
|
|
151
|
+
#
|
|
152
|
+
# @param uniform [String, Symbol] If a Symbol, :frog_paste is looked up as "in_FrogPaste", otherwise the Sting is used directly.
|
|
153
|
+
# @param value [Any] Value to set the uniform to
|
|
154
|
+
#
|
|
155
|
+
# @raise ShaderUniformError unless requested uniform is defined in vertex or fragment shaders.
|
|
156
|
+
def []=(uniform, value)
|
|
157
|
+
uniform = uniform_name_from_symbol(uniform) if uniform.is_a? Symbol
|
|
158
|
+
|
|
159
|
+
# Ensure that the program is current before setting values.
|
|
160
|
+
needs_use = !current?
|
|
161
|
+
enable if needs_use
|
|
162
|
+
set_uniform uniform_location(uniform), value
|
|
163
|
+
disable if needs_use
|
|
164
|
+
|
|
165
|
+
value
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
protected
|
|
169
|
+
# Set uniform without trying to force use of the program.
|
|
170
|
+
def set_uniform(location, value)
|
|
171
|
+
raise ShaderUniformError, "Shader uniform #{location.inspect} could not be set, since shader is not current" unless current?
|
|
172
|
+
|
|
173
|
+
return if location == INVALID_LOCATION # Not for end-users :)
|
|
174
|
+
|
|
175
|
+
case value
|
|
176
|
+
when true, GL_TRUE
|
|
177
|
+
glUniform1i location, 1
|
|
178
|
+
|
|
179
|
+
when false, GL_FALSE
|
|
180
|
+
glUniform1i location, 0
|
|
181
|
+
|
|
182
|
+
when Float
|
|
43
183
|
begin
|
|
44
|
-
|
|
184
|
+
glUniform1f location, value
|
|
45
185
|
rescue
|
|
186
|
+
glUniform1i location, value.to_i
|
|
46
187
|
end
|
|
188
|
+
|
|
189
|
+
when Integer
|
|
190
|
+
begin
|
|
191
|
+
glUniform1i location, value
|
|
192
|
+
rescue
|
|
193
|
+
glUniform1f location, value.to_f
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
when Gosu::Color
|
|
197
|
+
glUniform4f location, *value.to_opengl
|
|
198
|
+
|
|
199
|
+
when Array
|
|
200
|
+
size = value.size
|
|
201
|
+
|
|
202
|
+
raise ArgumentError, "Empty array not supported for uniform data" if size.zero?
|
|
203
|
+
raise ArgumentError, "Only support uniforms up to 4 elements" if size > 4
|
|
204
|
+
|
|
205
|
+
case value[0]
|
|
206
|
+
when Float
|
|
207
|
+
begin
|
|
208
|
+
GL.send "glUniform#{size}f", location, *value.map(&:to_f)
|
|
209
|
+
rescue
|
|
210
|
+
GL.send "glUniform#{size}i", location, *value.map(&:to_i)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
when Integer
|
|
214
|
+
begin
|
|
215
|
+
GL.send "glUniform#{size}i", location, *value.map(&:to_i)
|
|
216
|
+
rescue
|
|
217
|
+
GL.send "glUniform#{size}f", location, *value.map(&:to_f)
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
else
|
|
221
|
+
raise ArgumentError, "Uniform data type not supported for element of type: #{value[0].class}"
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
else
|
|
225
|
+
raise ArgumentError, "Uniform data type not supported for type: #{value.class}"
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
value
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
protected
|
|
232
|
+
def uniform_location(name, options = {})
|
|
233
|
+
options = {
|
|
234
|
+
required: true
|
|
235
|
+
}.merge! options
|
|
236
|
+
|
|
237
|
+
location = @uniform_locations[name]
|
|
238
|
+
if location
|
|
239
|
+
location
|
|
240
|
+
else
|
|
241
|
+
location = glGetUniformLocation @program, name.to_s
|
|
242
|
+
if options[:required] && location == INVALID_LOCATION
|
|
243
|
+
raise ShaderUniformError, "No #{name.inspect} uniform specified in program"
|
|
47
244
|
end
|
|
245
|
+
@uniform_locations[name] = location
|
|
48
246
|
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
public
|
|
250
|
+
def image=(image)
|
|
251
|
+
raise ShaderError, "Can't set image unless using shader" unless current?
|
|
252
|
+
|
|
253
|
+
if image
|
|
254
|
+
info = image.gl_tex_info
|
|
255
|
+
|
|
256
|
+
glActiveTexture GL_TEXTURE0
|
|
257
|
+
glBindTexture GL_TEXTURE_2D, info.tex_name
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
set_uniform uniform_location("in_TextureEnabled", required: false), !!image
|
|
49
261
|
|
|
50
262
|
@image = image
|
|
51
263
|
end
|
|
52
264
|
|
|
265
|
+
public
|
|
53
266
|
def color=(color)
|
|
54
|
-
|
|
267
|
+
opengl_color = case color
|
|
268
|
+
when Gosu::Color
|
|
269
|
+
color.to_opengl
|
|
270
|
+
when Integer
|
|
271
|
+
Gosu::Color.new(color).to_opengl
|
|
272
|
+
when Array
|
|
273
|
+
color
|
|
274
|
+
else
|
|
275
|
+
raise TypeError, "Expected Gosu::Color, Integer or opengl float array for color"
|
|
276
|
+
end
|
|
55
277
|
|
|
56
|
-
|
|
278
|
+
needs_use = !current?
|
|
279
|
+
enable if needs_use
|
|
280
|
+
location = glGetAttribLocation @program, "in_Color"
|
|
281
|
+
glVertexAttrib4f location, *opengl_color unless location == INVALID_LOCATION
|
|
282
|
+
disable if needs_use
|
|
57
283
|
|
|
58
|
-
glVertexAttrib4f attribute("in_Color"), *opengl_color
|
|
59
284
|
@color = opengl_color
|
|
60
285
|
end
|
|
286
|
+
|
|
287
|
+
protected
|
|
288
|
+
def attribute(name)
|
|
289
|
+
location = @attribute_locations[name]
|
|
290
|
+
if location
|
|
291
|
+
location
|
|
292
|
+
else
|
|
293
|
+
location = glGetAttribLocation @program, name.to_s
|
|
294
|
+
raise ShaderAttributeError, "No #{name} attribute specified in program" if location == INVALID_LOCATION
|
|
295
|
+
@attribute_locations[name] = location
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
protected
|
|
300
|
+
def compile(type, source)
|
|
301
|
+
shader = glCreateShader type
|
|
302
|
+
glShaderSource shader, source
|
|
303
|
+
glCompileShader shader
|
|
304
|
+
|
|
305
|
+
unless glGetShaderiv shader, GL_COMPILE_STATUS
|
|
306
|
+
error = glGetShaderInfoLog shader
|
|
307
|
+
error_lines = error.scan(/0\((\d+)\)+/m).map {|num| num.first.to_i }.uniq
|
|
308
|
+
|
|
309
|
+
if type == GL_VERTEX_SHADER
|
|
310
|
+
type_name = "Vertex"
|
|
311
|
+
source = @vertex_source
|
|
312
|
+
else
|
|
313
|
+
type_name = "Fragment"
|
|
314
|
+
source = @fragment_source
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
source_lines = source.split("\n")
|
|
318
|
+
lines = error_lines.map {|i| "#{i.to_s.rjust 3}: #{source_lines[i - 1].rstrip}" }.join "\n"
|
|
319
|
+
raise ShaderCompileError, "#{type_name} shader error: #{glGetShaderInfoLog(shader)}\n#{lines}"
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
shader
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
protected
|
|
326
|
+
def link
|
|
327
|
+
@program = glCreateProgram
|
|
328
|
+
glAttachShader @program, @vertex
|
|
329
|
+
glAttachShader @program, @fragment
|
|
330
|
+
glLinkProgram @program
|
|
331
|
+
|
|
332
|
+
unless glGetProgramiv @program, GL_LINK_STATUS
|
|
333
|
+
raise ShaderLinkError, "Shader link error: #{glGetProgramInfoLog(@program)}"
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
nil
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
protected
|
|
340
|
+
# Symbol => load a built-in
|
|
341
|
+
# Filename => load file
|
|
342
|
+
# Source => use directly.
|
|
343
|
+
#
|
|
344
|
+
# Also recursively replaces #include
|
|
345
|
+
# TODO: What about line numbers getting messed up by #include?
|
|
346
|
+
def process_source(shader, extension)
|
|
347
|
+
source = if shader.is_a? Symbol
|
|
348
|
+
file = File.expand_path "#{shader}#{extension}", BUILT_IN_SHADER_PATH
|
|
349
|
+
unless File.exists? file
|
|
350
|
+
raise ShaderLoadError, "Failed to load built-in shader: #{shader.inspect}"
|
|
351
|
+
end
|
|
352
|
+
File.read file
|
|
353
|
+
|
|
354
|
+
elsif File.exists? shader
|
|
355
|
+
File.read shader
|
|
356
|
+
else
|
|
357
|
+
shader
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
replace_include source
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
protected
|
|
364
|
+
# Recursively replace #include.
|
|
365
|
+
#
|
|
366
|
+
# * Replace '#include <rand>' with the contents of include/rand.glsl
|
|
367
|
+
# * Replace '#include "/home/spooner/my_shader_functions/frog.glsl"' with the contents of that file.
|
|
368
|
+
#
|
|
369
|
+
# @return [String] Source code that has been expanded.
|
|
370
|
+
def replace_include(source)
|
|
371
|
+
source.gsub! /^#include\s+<([^>]*)>/ do
|
|
372
|
+
replace_include File.read(File.expand_path("#{$1}.glsl", INCLUDE_PATH))
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
source.gsub /^#include\s+"([^"]*)"/ do
|
|
376
|
+
replace_include File.read($1)
|
|
377
|
+
end
|
|
378
|
+
end
|
|
61
379
|
end
|
|
62
380
|
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#version 110
|
|
2
|
+
|
|
3
|
+
// Bloom filter
|
|
4
|
+
// http://myheroics.wordpress.com/2008/09/04/glsl-bloom-shader/
|
|
5
|
+
//
|
|
6
|
+
// Spooner: Added uniforms for setting bloom intensity.
|
|
7
|
+
|
|
8
|
+
uniform sampler2D in_Texture; // Original in_Texture.
|
|
9
|
+
varying vec2 var_TexCoord; // Pixel to process on this pass
|
|
10
|
+
|
|
11
|
+
uniform float in_GlareSize; // 0.004 is good
|
|
12
|
+
uniform float in_Power; // 0.25 is good
|
|
13
|
+
|
|
14
|
+
void main()
|
|
15
|
+
{
|
|
16
|
+
vec4 sum = vec4(0);
|
|
17
|
+
int i, j;
|
|
18
|
+
|
|
19
|
+
for(i = -4; i < 4; i++)
|
|
20
|
+
{
|
|
21
|
+
for (j = -3; j < 3; j++)
|
|
22
|
+
{
|
|
23
|
+
sum += texture2D(in_Texture, var_TexCoord + vec2(j, i) * in_GlareSize) * in_Power;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
vec4 base_color = texture2D(in_Texture, var_TexCoord);
|
|
28
|
+
|
|
29
|
+
if (base_color.r < 0.3)
|
|
30
|
+
{
|
|
31
|
+
gl_FragColor = sum * sum * 0.012 + base_color;
|
|
32
|
+
}
|
|
33
|
+
else if(base_color.r < 0.5)
|
|
34
|
+
{
|
|
35
|
+
gl_FragColor = sum * sum * 0.009 + base_color;
|
|
36
|
+
}
|
|
37
|
+
else
|
|
38
|
+
{
|
|
39
|
+
gl_FragColor = sum * sum * 0.0075 + base_color;
|
|
40
|
+
}
|
|
41
|
+
}
|