Class: Engine::Shader
- Inherits:
-
Object
- Object
- Engine::Shader
- Includes:
- Serializable
- Defined in:
- lib/engine/shader.rb
Instance Attribute Summary collapse
-
#source ⇒ Object
readonly
Returns the value of attribute source.
Class Method Summary collapse
- .colour ⇒ Object
- .default ⇒ Object
- .for(vertex_path, fragment_path, source: :game) ⇒ Object
- .from_file(vertex_path, fragment_path, source: :game) ⇒ Object
- .from_serializable_data(data) ⇒ Object
- .fullscreen ⇒ Object
- .instanced_sprite ⇒ Object
- .point_shadow ⇒ Object
- .shadow ⇒ Object
- .skybox_cubemap ⇒ Object
- .sprite ⇒ Object
- .text ⇒ Object
- .ui_sprite ⇒ Object
- .ui_text ⇒ Object
- .vertex_lit ⇒ Object
Instance Method Summary collapse
- #awake ⇒ Object
- #compile_shader(shader, type) ⇒ Object
- #cubemap_fallback(name) ⇒ Object
- #expected_textures ⇒ Object
- #preprocess_shader(path, included = []) ⇒ Object
- #resolve_shader_path(shader) ⇒ Object
- #serializable_data ⇒ Object
- #set_float(name, float) ⇒ Object
- #set_int(name, int) ⇒ Object
- #set_mat4(name, mat) ⇒ Object
- #set_vec2(name, vec) ⇒ Object
- #set_vec3(name, vec) ⇒ Object
- #set_vec4(name, vec) ⇒ Object
- #texture_fallback(name) ⇒ Object
- #use ⇒ Object
Methods included from Serializable
allowed_class?, get_class, included, register_class, #uuid
Instance Attribute Details
#source ⇒ Object (readonly)
Returns the value of attribute source.
5 6 7 |
# File 'lib/engine/shader.rb', line 5 def source @source end |
Class Method Details
.colour ⇒ Object
62 63 64 |
# File 'lib/engine/shader.rb', line 62 def self.colour @colour ||= Engine::Shader.for('colour_vertex.glsl', 'colour_frag.glsl', source: :engine) end |
.default ⇒ Object
26 27 28 |
# File 'lib/engine/shader.rb', line 26 def self.default @default ||= Shader.for('mesh_vertex.glsl', 'mesh_frag.glsl', source: :engine) end |
.for(vertex_path, fragment_path, source: :game) ⇒ Object
9 10 11 12 |
# File 'lib/engine/shader.rb', line 9 def self.for(vertex_path, fragment_path, source: :game) key = [vertex_path, fragment_path, source] @cache[key] ||= create(vertex_path: vertex_path, fragment_path: fragment_path, source: source) end |
.from_file(vertex_path, fragment_path, source: :game) ⇒ Object
14 15 16 |
# File 'lib/engine/shader.rb', line 14 def self.from_file(vertex_path, fragment_path, source: :game) self.for(vertex_path, fragment_path, source: source) end |
.from_serializable_data(data) ⇒ Object
18 19 20 |
# File 'lib/engine/shader.rb', line 18 def self.from_serializable_data(data) self.for(data[:vertex_path], data[:fragment_path], source: (data[:source] || :game).to_sym) end |
.fullscreen ⇒ Object
58 59 60 |
# File 'lib/engine/shader.rb', line 58 def self.fullscreen @fullscreen ||= Engine::Shader.for('fullscreen_vertex.glsl', 'fullscreen_frag.glsl', source: :engine) end |
.instanced_sprite ⇒ Object
42 43 44 |
# File 'lib/engine/shader.rb', line 42 def self.instanced_sprite @instanced_sprite ||= Engine::Shader.for('instanced_sprite_vertex.glsl', 'instanced_sprite_frag.glsl', source: :engine) end |
.point_shadow ⇒ Object
70 71 72 |
# File 'lib/engine/shader.rb', line 70 def self.point_shadow @point_shadow ||= Engine::Shader.for('point_shadow_vertex.glsl', 'point_shadow_frag.glsl', source: :engine) end |
.shadow ⇒ Object
66 67 68 |
# File 'lib/engine/shader.rb', line 66 def self.shadow @shadow ||= Engine::Shader.for('shadow_vertex.glsl', 'shadow_frag.glsl', source: :engine) end |
.skybox_cubemap ⇒ Object
34 35 36 |
# File 'lib/engine/shader.rb', line 34 def self.skybox_cubemap @skybox_cubemap ||= Shader.for('fullscreen_vertex.glsl', 'skybox_cubemap_frag.glsl', source: :engine) end |
.sprite ⇒ Object
38 39 40 |
# File 'lib/engine/shader.rb', line 38 def self.sprite @sprite ||= Engine::Shader.for('sprite_vertex.glsl', 'sprite_frag.glsl', source: :engine) end |
.text ⇒ Object
46 47 48 |
# File 'lib/engine/shader.rb', line 46 def self.text @text ||= Engine::Shader.for('text_vertex.glsl', 'text_frag.glsl', source: :engine) end |
.ui_sprite ⇒ Object
54 55 56 |
# File 'lib/engine/shader.rb', line 54 def self.ui_sprite @ui_sprite ||= Engine::Shader.for('ui_sprite_vertex.glsl', 'ui_sprite_frag.glsl', source: :engine) end |
.ui_text ⇒ Object
50 51 52 |
# File 'lib/engine/shader.rb', line 50 def self.ui_text @ui_text ||= Engine::Shader.for('text_vertex.glsl', 'text_frag.glsl', source: :engine) end |
.vertex_lit ⇒ Object
30 31 32 |
# File 'lib/engine/shader.rb', line 30 def self.vertex_lit @vertex_lit ||= Engine::Shader.for('vertex_lit_vertex.glsl', 'vertex_lit_frag.glsl', source: :engine) end |
Instance Method Details
#awake ⇒ Object
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 |
# File 'lib/engine/shader.rb', line 74 def awake @texture_fallbacks = {} @cubemap_fallbacks = {} @vertex_shader = compile_shader(@vertex_path, Engine::GL::VERTEX_SHADER) @fragment_shader = compile_shader(@fragment_path, Engine::GL::FRAGMENT_SHADER) @program = Engine::GL.CreateProgram Engine::GL.AttachShader(@program, @vertex_shader) Engine::GL.AttachShader(@program, @fragment_shader) Engine::GL.LinkProgram(@program) linked_buf = ' ' * 4 Engine::GL.GetProgramiv(@program, Engine::GL::LINK_STATUS, linked_buf) linked = linked_buf.unpack('L')[0] if linked == 0 compile_log = ' ' * 1024 Engine::GL.GetProgramInfoLog(@program, 1023, nil, compile_log) vertex_log = ' ' * 1024 Engine::GL.GetShaderInfoLog(@vertex_shader, 1023, nil, vertex_log) fragment_log = ' ' * 1024 Engine::GL.GetShaderInfoLog(@fragment_shader, 1023, nil, fragment_log) puts "Shader program failed to link" puts compile_log.strip puts vertex_log.strip puts fragment_log.strip end @uniform_cache = {} @uniform_locations = {} end |
#compile_shader(shader, type) ⇒ Object
103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/engine/shader.rb', line 103 def compile_shader(shader, type) handle = Engine::GL.CreateShader(type) path = resolve_shader_path(shader) source = preprocess_shader(path) parse_texture_fallbacks(source) s_srcs = [source].pack('p') s_lens = [source.bytesize].pack('I') Engine::GL.ShaderSource(handle, 1, s_srcs, s_lens) Engine::GL.CompileShader(handle) handle end |
#cubemap_fallback(name) ⇒ Object
131 132 133 |
# File 'lib/engine/shader.rb', line 131 def cubemap_fallback(name) @cubemap_fallbacks[name] end |
#expected_textures ⇒ Object
127 128 129 |
# File 'lib/engine/shader.rb', line 127 def expected_textures @texture_fallbacks.keys end |
#preprocess_shader(path, included = []) ⇒ Object
135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/engine/shader.rb', line 135 def preprocess_shader(path, included = []) return "" if included.include?(path) included << path source = File.read(path) dir = File.dirname(path) source.gsub(/#include\s+"([^"]+)"/) do include_path = File.join(dir, $1) preprocess_shader(include_path, included) end end |
#resolve_shader_path(shader) ⇒ Object
115 116 117 118 119 120 121 |
# File 'lib/engine/shader.rb', line 115 def resolve_shader_path(shader) if @source == :engine File.join(ENGINE_DIR, "shaders", shader) else File.join(GAME_DIR, "shaders", shader) end end |
#serializable_data ⇒ Object
22 23 24 |
# File 'lib/engine/shader.rb', line 22 def serializable_data { vertex_path: @vertex_path, fragment_path: @fragment_path, source: @source } end |
#set_float(name, float) ⇒ Object
194 195 196 197 198 |
# File 'lib/engine/shader.rb', line 194 def set_float(name, float) return if @uniform_cache[name] == float @uniform_cache[name] = float Engine::GL.Uniform1f(uniform_location(name), float) end |
#set_int(name, int) ⇒ Object
188 189 190 191 192 |
# File 'lib/engine/shader.rb', line 188 def set_int(name, int) return if @uniform_cache[name] == int @uniform_cache[name] = int Engine::GL.Uniform1i(uniform_location(name), int) end |
#set_mat4(name, mat) ⇒ Object
176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/engine/shader.rb', line 176 def set_mat4(name, mat) return if @uniform_cache[name] == mat @uniform_cache[name] = mat mat_array = [ mat[0, 0], mat[0, 1], mat[0, 2], mat[0, 3], mat[1, 0], mat[1, 1], mat[1, 2], mat[1, 3], mat[2, 0], mat[2, 1], mat[2, 2], mat[2, 3], mat[3, 0], mat[3, 1], mat[3, 2], mat[3, 3] ] Engine::GL.UniformMatrix4fv(uniform_location(name), 1, Engine::GL::FALSE, mat_array.pack('F*')) end |
#set_vec2(name, vec) ⇒ Object
152 153 154 155 156 |
# File 'lib/engine/shader.rb', line 152 def set_vec2(name, vec) return if @uniform_cache[name] == vec @uniform_cache[name] = vec Engine::GL.Uniform2f(uniform_location(name), vec[0], vec[1]) end |
#set_vec3(name, vec) ⇒ Object
158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/engine/shader.rb', line 158 def set_vec3(name, vec) vector = if vec.is_a?(Vector) vec else Vector[vec[:r], vec[:g], vec[:b]] end cache_key = [vector[0], vector[1], vector[2]] return if @uniform_cache[name] == cache_key @uniform_cache[name] = cache_key Engine::GL.Uniform3f(uniform_location(name), vector[0], vector[1], vector[2]) end |
#set_vec4(name, vec) ⇒ Object
170 171 172 173 174 |
# File 'lib/engine/shader.rb', line 170 def set_vec4(name, vec) return if @uniform_cache[name] == vec @uniform_cache[name] = vec Engine::GL.Uniform4f(uniform_location(name), vec[0], vec[1], vec[2], vec[3]) end |
#texture_fallback(name) ⇒ Object
123 124 125 |
# File 'lib/engine/shader.rb', line 123 def texture_fallback(name) @texture_fallbacks[name] || :white end |
#use ⇒ Object
148 149 150 |
# File 'lib/engine/shader.rb', line 148 def use Engine::GL.UseProgram(@program) end |