diff --git a/runtime/lib/gl_program.rb b/runtime/lib/gl_program.rb index 26a0d25..b488e22 100644 --- a/runtime/lib/gl_program.rb +++ b/runtime/lib/gl_program.rb @@ -1,9 +1,14 @@ class GLProgram # @overload initialize(*shaders, options = {}) # - # @param shaders [Array] Shaders to attach to the program. - # @param options [Hash] Optional parameters. + # @param shaders [Array] + # Shaders to attach to the program. + # @param options [Hash] + # Optional parameters. + # @option options [Array] :uniforms + # Names of uniforms to load locations of for this program. def initialize(*args) + options = args.last.is_a?(Hash) ? args.pop : {} args.each do |arg| if arg.is_a?(GLShader) attach_shader(arg) @@ -11,6 +16,16 @@ class GLProgram raise NotImplementedError.new("Other arguments not yet implemented") end end + options.each do |option, value| + case option + when :uniforms + value.each do |uniform| + load_uniform_location(uniform) + end + else + raise "Unknown option #{option.inspect}" + end + end link end end diff --git a/runtime/lib/window.rb b/runtime/lib/window.rb index 2f94d19..651d427 100644 --- a/runtime/lib/window.rb +++ b/runtime/lib/window.rb @@ -36,11 +36,22 @@ class Window } program_sources.each do |program, (v_src_fname, f_src_fname)| - v_shader = GLShader.new(:vertex, Runtime.read(:shader, v_src_fname)) + v_src = Runtime.read(:shader, v_src_fname) + v_shader = GLShader.new(:vertex, v_src) v_shader or raise "Could not find shader #{v_src_fname}" - f_shader = GLShader.new(:fragment, Runtime.read(:shader, f_src_fname)) + + f_src = Runtime.read(:shader, f_src_fname) + f_shader = GLShader.new(:fragment, f_src) f_shader or raise "Could not find shader #{f_src_fname}" - @programs[program] = GLProgram.new(v_shader, f_shader) + + uniforms = (v_src + f_src).lines.map do |line| + if line =~ /\buniform\s.*\s(\S+);/ + $1 + end + end.compact + + @programs[program] = GLProgram.new(v_shader, f_shader, + uniforms: uniforms) end end end diff --git a/src/GLProgram.cc b/src/GLProgram.cc index 0412506..8610b53 100644 --- a/src/GLProgram.cc +++ b/src/GLProgram.cc @@ -1,10 +1,6 @@ #include "GLProgram.h" #include "GLShader.h" - -typedef struct -{ - GLuint id; -} GLProgram; +#include static VALUE ruby_class; @@ -92,6 +88,43 @@ static VALUE GLProgram_link(VALUE self) return Qnil; } +static VALUE GLProgram_load_uniform_location(VALUE self, VALUE uniform) +{ + static const char * uniform_names[] = { + "viewport_size", + "position", + "size", + "texture", + "color", + }; + GLProgram * glprogram; + Data_Get_Struct(self, GLProgram, glprogram); + uniform = rb_funcall(uniform, rb_intern("to_s"), 0); + const char * uniform_cstr = StringValueCStr(uniform); + int uniform_index = -1; + for (int i = 0; + i < (int)(sizeof(uniform_names) / sizeof(uniform_names[0])); + i++) + { + if (strcmp(uniform_cstr, uniform_names[i]) == 0) + { + uniform_index = i; + break; + } + } + if (uniform_index >= 0) + { + glprogram->uniforms[uniform_index] = glGetUniformLocation(glprogram->id, uniform_cstr); + } + else + { + rb_raise(rb_eRuntimeError, + "Unknown uniform name '%s'", + uniform_cstr); + } + return Qnil; +} + void GLProgram_Init() { ruby_class = rb_define_class("GLProgram", rb_cObject); @@ -99,6 +132,7 @@ void GLProgram_Init() rb_define_method(ruby_class, "attach_shader", (VALUE(*)(...))GLProgram_attach_shader, 1); rb_define_method(ruby_class, "bind_attribute", (VALUE(*)(...))GLProgram_bind_attribute, 2); rb_define_method(ruby_class, "link", (VALUE(*)(...))GLProgram_link, 0); + rb_define_method(ruby_class, "load_uniform_location", (VALUE(*)(...))GLProgram_load_uniform_location, 1); } GLuint GLProgram_GetID(VALUE program) @@ -107,21 +141,3 @@ GLuint GLProgram_GetID(VALUE program) Data_Get_Struct(program, GLProgram, glprogram); return glprogram->id; } - -#if 0 -GLint GLProgram::get_uniform(const std::string & uniform_name) -{ - if (m_id > 0u) - { - auto it = m_uniforms.find(uniform_name); - if (it != m_uniforms.end()) - { - return it->second; - } - GLint loc = glGetUniformLocation(m_id, uniform_name.c_str()); - m_uniforms[uniform_name] = loc; - return loc; - } - return -1; -} -#endif diff --git a/src/GLProgram.h b/src/GLProgram.h index 226cc3d..135095e 100644 --- a/src/GLProgram.h +++ b/src/GLProgram.h @@ -3,6 +3,22 @@ #include "ruby.h" #include "gl3w.h" +#include + +enum +{ + UNIFORM_VIEWPORT_SIZE, + UNIFORM_POSITION, + UNIFORM_SIZE, + UNIFORM_TEXTURE, + UNIFORM_COLOR, +}; + +struct GLProgram +{ + GLuint id; + std::unordered_map uniforms; +}; void GLProgram_Init(); GLuint GLProgram_GetID(VALUE program);