Class: CyberarmEngine::Shader
- Inherits:
-
Object
- Object
- CyberarmEngine::Shader
- Includes:
- OpenGL
- Defined in:
- lib/cyberarm_engine/shader.rb
Overview
Constant Summary collapse
- @@shaders =
{}
Instance Attribute Summary collapse
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#program ⇒ Object
readonly
Returns the value of attribute program.
Class Method Summary collapse
- .active_shader ⇒ Object
- .active_shader=(instance) ⇒ Object
- .add(name, instance) ⇒ Object
- .attribute_location(variable) ⇒ Object
- .available?(name) ⇒ Boolean
- .get(name) ⇒ Object
- .set_uniform(variable, value) ⇒ Object
- .stop ⇒ Object
- .use(name, &block) ⇒ Object
Instance Method Summary collapse
- #attribute_location(variable) ⇒ Object
- #compile_shaders ⇒ Object
- #compiled? ⇒ Boolean
- #create_shaders ⇒ Object
-
#initialize(name:, vertex: "shaders/default.vert", fragment:) ⇒ Shader
constructor
A new instance of Shader.
- #set_uniform(variable, value, location = nil) ⇒ Object
- #shader_files_exist? ⇒ Boolean
- #stop ⇒ Object
- #use(&block) ⇒ Object
-
#variable(variable) ⇒ Object
Returns the location of a uniform variable.
Constructor Details
#initialize(name:, vertex: "shaders/default.vert", fragment:) ⇒ Shader
Returns a new instance of Shader.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/cyberarm_engine/shader.rb', line 57 def initialize(name:, vertex: "shaders/default.vert", fragment:) @name = name @vertex_file = vertex @fragment_file = fragment @compiled = false @program = nil @error_buffer_size = 1024 @variable_missing = {} raise ArgumentError, "Shader files not found: #{@vertex_file} or #{@fragment_file}" unless shader_files_exist? create_shaders compile_shaders # Only add shader if it successfully compiles if @compiled Shader.add(@name, self) else puts "FAILED to compile shader: #{@name}", "" end end |
Instance Attribute Details
#name ⇒ Object (readonly)
Returns the value of attribute name.
56 57 58 |
# File 'lib/cyberarm_engine/shader.rb', line 56 def name @name end |
#program ⇒ Object (readonly)
Returns the value of attribute program.
56 57 58 |
# File 'lib/cyberarm_engine/shader.rb', line 56 def program @program end |
Class Method Details
.active_shader ⇒ Object
28 29 30 |
# File 'lib/cyberarm_engine/shader.rb', line 28 def self.active_shader @active_shader end |
.active_shader=(instance) ⇒ Object
32 33 34 |
# File 'lib/cyberarm_engine/shader.rb', line 32 def self.active_shader=(instance) @active_shader = instance end |
.add(name, instance) ⇒ Object
7 8 9 |
# File 'lib/cyberarm_engine/shader.rb', line 7 def self.add(name, instance) @@shaders[name] = instance end |
.attribute_location(variable) ⇒ Object
46 47 48 49 |
# File 'lib/cyberarm_engine/shader.rb', line 46 def self.attribute_location(variable) raise RuntimeError, "No active shader!" unless Shader.active_shader Shader.active_shader.attribute_location(variable) end |
.available?(name) ⇒ Boolean
20 21 22 |
# File 'lib/cyberarm_engine/shader.rb', line 20 def self.available?(name) @@shaders.dig(name).is_a?(Shader) end |
.get(name) ⇒ Object
24 25 26 |
# File 'lib/cyberarm_engine/shader.rb', line 24 def self.get(name) @@shaders.dig(name) end |
.set_uniform(variable, value) ⇒ Object
51 52 53 54 |
# File 'lib/cyberarm_engine/shader.rb', line 51 def self.set_uniform(variable, value) raise RuntimeError, "No active shader!" unless Shader.active_shader Shader.active_shader.set_uniform(variable, value) end |
.stop ⇒ Object
36 37 38 39 40 41 42 43 44 |
# File 'lib/cyberarm_engine/shader.rb', line 36 def self.stop shader = Shader.active_shader if shader shader.stop else raise ArgumentError, "No active shader to stop!" end end |
.use(name, &block) ⇒ Object
11 12 13 14 15 16 17 18 |
# File 'lib/cyberarm_engine/shader.rb', line 11 def self.use(name, &block) shader = @@shaders.dig(name) if shader shader.use(&block) else raise ArgumentError, "Shader '#{name}' not found!" end end |
Instance Method Details
#attribute_location(variable) ⇒ Object
184 185 186 |
# File 'lib/cyberarm_engine/shader.rb', line 184 def attribute_location(variable) glGetUniformLocation(@program, variable) end |
#compile_shaders ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/cyberarm_engine/shader.rb', line 98 def compile_shaders return unless shader_files_exist? glCompileShader(@vertex) buffer = ' ' glGetShaderiv(@vertex, GL_COMPILE_STATUS, buffer) compiled = buffer.unpack('L')[0] if compiled == 0 log = ' ' * @error_buffer_size glGetShaderInfoLog(@vertex, @error_buffer_size, nil, log) puts "Shader Error: Program \"#{@name}\"" puts " Vectex Shader InfoLog:", " #{log.strip.split("\n").join("\n ")}\n\n" puts " Shader Compiled status: #{compiled}" puts " NOTE: assignment of uniforms in shaders is illegal!" puts return end glCompileShader(@fragment) buffer = ' ' glGetShaderiv(@fragment, GL_COMPILE_STATUS, buffer) compiled = buffer.unpack('L')[0] if compiled == 0 log = ' ' * @error_buffer_size glGetShaderInfoLog(@fragment, @error_buffer_size, nil, log) puts "Shader Error: Program \"#{@name}\"" puts " Fragment Shader InfoLog:", " #{log.strip.split("\n").join("\n ")}\n\n" puts " Shader Compiled status: #{compiled}" puts " NOTE: assignment of uniforms in shader is illegal!" puts return end @program = glCreateProgram glAttachShader(@program, @vertex) glAttachShader(@program, @fragment) glLinkProgram(@program) buffer = ' ' glGetProgramiv(@program, GL_LINK_STATUS, buffer) linked = buffer.unpack('L')[0] if linked == 0 log = ' ' * @error_buffer_size glGetProgramInfoLog(@program, @error_buffer_size, nil, log) puts "Shader Error: Program \"#{@name}\"" puts " Program InfoLog:", " #{log.strip.split("\n").join("\n ")}\n\n" end @compiled = linked == 0 ? false : true end |
#compiled? ⇒ Boolean
180 181 182 |
# File 'lib/cyberarm_engine/shader.rb', line 180 def compiled? @compiled end |
#create_shaders ⇒ Object
85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/cyberarm_engine/shader.rb', line 85 def create_shaders @vertex = glCreateShader(GL_VERTEX_SHADER) @fragment = glCreateShader(GL_FRAGMENT_SHADER) source = [File.read(@vertex_file)].pack('p') size = [File.size(@vertex_file)].pack('I') glShaderSource(@vertex, 1, source, size) source = [File.read(@fragment_file)].pack('p') size = [File.size(@fragment_file)].pack('I') glShaderSource(@fragment, 1, source, size) end |
#set_uniform(variable, value, location = nil) ⇒ Object
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/cyberarm_engine/shader.rb', line 188 def set_uniform(variable, value, location = nil) attr_loc = location ? location : attribute_location(variable) case value.class.to_s.downcase.to_sym when :integer glUniform1i(attr_loc, value) when :float glUniform1f(attr_loc, value) when :string when :array else raise NotImplementedError, "Shader support for #{value.class.inspect} not implemented." end Window.handle_gl_error end |
#shader_files_exist? ⇒ Boolean
81 82 83 |
# File 'lib/cyberarm_engine/shader.rb', line 81 def shader_files_exist? File.exist?(@vertex_file) && File.exist?(@fragment_file) end |
#stop ⇒ Object
175 176 177 178 |
# File 'lib/cyberarm_engine/shader.rb', line 175 def stop Shader.active_shader = nil if Shader.active_shader == self glUseProgram(0) end |
#use(&block) ⇒ Object
162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/cyberarm_engine/shader.rb', line 162 def use(&block) return unless compiled? raise "Another shader is already in use! #{Shader.active_shader.name.inspect}" if Shader.active_shader Shader.active_shader=self glUseProgram(@program) if block block.call(self) stop end end |
#variable(variable) ⇒ Object
Returns the location of a uniform variable
153 154 155 156 157 158 159 160 |
# File 'lib/cyberarm_engine/shader.rb', line 153 def variable(variable) loc = glGetUniformLocation(@program, variable) if (loc == -1) puts "Shader Error: Program \"#{@name}\" has no such uniform named \"#{variable}\"", " Is it used in the shader? GLSL may have optimized it out.", " Is it miss spelled?" unless @variable_missing[variable] @variable_missing[variable] = true end return loc end |