diff --git a/src/gltk/program.d b/src/gltk/program.d index 2544b69..839497a 100644 --- a/src/gltk/program.d +++ b/src/gltk/program.d @@ -3,10 +3,21 @@ import gltk.shader; import derelict.opengl; import std.string; -class Program +class Program(uniforms...) { + /* The number of template parameters must be a multiple of 2. */ + static assert((uniforms.length % 2) == 0); + private GLuint m_id; + static foreach (i, v; uniforms) + { + static if ((i % 2) == 0) + { + mixin("private GLint m_uniform_" ~ v ~ ";"); + } + } + this(Args...)(Args args) { m_id = glCreateProgram(); @@ -35,7 +46,7 @@ class Program glBindAttribLocation(m_id, index, name.toStringz()); } - void link() const + void link() { glLinkProgram(m_id); @@ -56,6 +67,14 @@ class Program } throw new Exception(message); } + + static foreach(i, v; uniforms) + { + static if ((i % 2) == 0) + { + mixin("m_uniform_" ~ v ~ " = glGetUniformLocation(m_id, \"" ~ v ~ "\");"); + } + } } GLint get_uniform_location(string uniform_name) const @@ -63,7 +82,7 @@ class Program return glGetUniformLocation(m_id, uniform_name.toStringz()); } - void get_uniform_locations(Args...)(string uniform_name, GLint * uniform_location, Args args) + void get_uniform_locations(Args...)(string uniform_name, GLint * uniform_location, Args args) const { *uniform_location = get_uniform_location(uniform_name); static if (args.length > 0u) @@ -82,19 +101,80 @@ class Program glUseProgram(m_id); } - private void build(Args...)(Shader s, Args args) const + private static string uniform_param_decl_list(string spec) + { + int count = spec[0] - '0'; + string type; + if (spec[1] == 'i') + { + type = "GLint"; + } + else if (spec[1..2] == "ui") + { + type = "GLuint"; + } + else if (spec[1] == 'f') + { + type = "GLfloat"; + } + assert(type != ""); + if (spec[$ - 1] == 'v') + { + return "uint count, const " ~ type ~ " * v"; + } + else + { + string[] decls; + for (int i = 0; i < count; i++) + { + decls ~= type ~ " v" ~ cast(char)('0' + i); + } + return decls.join(", "); + } + } + + private static string uniform_param_list(string spec) + { + int count = spec[0] - '0'; + if (spec[$ - 1] == 'v') + { + return "count, v"; + } + else + { + string[] vees; + for (int i = 0; i < count; i++) + { + vees ~= "v" ~ cast(char)('0' + i); + } + return vees.join(", "); + } + } + + static foreach (i, v; uniforms) + { + static if ((i % 2) == 0) + { + mixin("void set_" ~ v ~ "(" ~ uniform_param_decl_list(uniforms[i + 1]) ~ ")" + "{" + " glUniform" ~ uniforms[i + 1] ~ "(m_uniform_" ~ v ~ ", " ~ uniform_param_list(uniforms[i + 1]) ~ ");" + "}"); + } + } + + private void build(Args...)(Shader s, Args args) { attach_shader(s); build(args); } - private void build(Args...)(string attrib_name, uint index, Args args) const + private void build(Args...)(string attrib_name, uint index, Args args) { bind_attrib_location(attrib_name, index); build(args); } - private void build() const + private void build() { link(); } diff --git a/src/jes/gui/package.d b/src/jes/gui/package.d index 2ea4815..bf7a3a1 100644 --- a/src/jes/gui/package.d +++ b/src/jes/gui/package.d @@ -8,11 +8,8 @@ import jes.gui.font; class Gui { jtk.Window[] m_windows; - gltk.Program m_text_program; - GLint m_viewport_size; - GLint m_texture; - GLint m_color; - GLint m_position; + alias TextProgram = gltk.Program!("viewport_size", "2i", "texture", "1i", "color", "4f", "position", "2i"); + TextProgram m_text_program; int width; int height; @@ -47,12 +44,7 @@ class Gui v_shader.set_source_from_file("share/jes/shaders/text.v.glsl"); auto f_shader = new gltk.Shader(GL_FRAGMENT_SHADER); f_shader.set_source_from_file("share/jes/shaders/text.f.glsl"); - m_text_program = new gltk.Program(v_shader, f_shader, "coords", 0); - m_text_program.get_uniform_locations( - "viewport_size", &m_viewport_size, - "texture", &m_texture, - "color", &m_color, - "position", &m_position); + m_text_program = new TextProgram(v_shader, f_shader, "coords", 0); glActiveTexture(GL_TEXTURE0); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -93,10 +85,10 @@ class Gui auto font = new Font("share/jes/fonts/freefont-ttf-20120503/FreeMono.ttf", 20); auto glyph = font.get_glyph('h'); m_text_program.use(); - glUniform2i(m_viewport_size, width, height); - glUniform1i(m_texture, 0); - glUniform4f(m_color, 1.0, 1.0, 1.0, 1.0); - glUniform2i(m_position, 10, 10); + m_text_program.set_viewport_size(width, height); + m_text_program.set_texture(0); + m_text_program.set_color(1.0, 1.0, 1.0, 1.0); + m_text_program.set_position(100, 10); glyph.render(); m_windows[0].swap_buffers(); }