From: Sam Moore Date: Mon, 16 Jun 2014 03:13:16 +0000 (+0800) Subject: GLSL Shaders -> Files (instead of #define) X-Git-Url: https://git.ucc.asn.au/?p=ipdf%2Fcode.git;a=commitdiff_plain;h=433bde2ed090928b264203c9f422a5b220857120 GLSL Shaders -> Files (instead of #define) So we can edit them without going insane. --- diff --git a/bin/ipdf b/bin/ipdf index bb1314c..a5f1124 100755 Binary files a/bin/ipdf and b/bin/ipdf differ diff --git a/src/log.h b/src/log.h index a98a8cc..fdf30a7 100644 --- a/src/log.h +++ b/src/log.h @@ -9,6 +9,7 @@ #include #include #include +#include // for strerror etc inline std::string methodName(const std::string& prettyFunction) { diff --git a/src/screen.cpp b/src/screen.cpp index 6d67820..5bca554 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -8,47 +8,8 @@ #include "bufferbuilder.h" #include "shaderprogram.h" -#define BASICTEX_VERT \ - "#version 140\n"\ - "#extension GL_ARB_shading_language_420pack : require\n"\ - "#extension GL_ARB_explicit_attrib_location : require\n"\ - "\n"\ - "layout(std140, binding=0) uniform Viewport\n"\ - "{\n"\ - "\tfloat width;\n"\ - "\tfloat height;\n"\ - "};\n"\ - "\n"\ - "layout(location = 0) in vec2 position;\n"\ - "layout(location = 1) in vec2 tex_coord;\n"\ - "\n"\ - "out vec2 fp_tex_coord;\n"\ - "\n"\ - "void main()\n"\ - "{\n"\ - "\t// Transform to clip coordinates (-1,1, -1,1).\n"\ - "\tgl_Position.x = (position.x*2/width) - 1;\n"\ - "\tgl_Position.y = 1 - (position.y*2/height);\n"\ - "\tgl_Position.z = 0.0;\n"\ - "\tgl_Position.w = 1.0;\n"\ - "\tfp_tex_coord = tex_coord;\n"\ - "}\n" - -#define BASICTEX_FRAG \ - "#version 140\n"\ - "\n"\ - "in vec2 fp_tex_coord;\n"\ - "\n"\ - "out vec4 output_colour;\n"\ - "\n"\ - "uniform sampler2D tex;\n"\ - "uniform vec4 colour;\n"\ - "\n"\ - "void main()\n"\ - "{\n"\ - "\toutput_colour = colour;\n"\ - "\toutput_colour.a = texture(tex, fp_tex_coord).r;\n"\ - "}\n" +#define BASICTEX_VERT "shaders/basictex_vert.glsl" +#define BASICTEX_FRAG "shaders/basictex_frag.glsl" using namespace IPDF; using namespace std; diff --git a/src/shaderprogram.cpp b/src/shaderprogram.cpp index eb7a82d..1f5e9e2 100644 --- a/src/shaderprogram.cpp +++ b/src/shaderprogram.cpp @@ -15,6 +15,9 @@ ShaderProgram::~ShaderProgram() glDeleteProgram(m_program); } +/** + * This is only called once, does it need a function? + */ void ShaderProgram::LazyCreateProgram() { if (!m_program) @@ -23,42 +26,81 @@ void ShaderProgram::LazyCreateProgram() } } -bool ShaderProgram::AttachShader(const char *src, GLenum type) +/** + * Get GLSL shader source from a file as a string + * @param src_file filename to get the shader source from + * @returns a char* string allocated with new[] (remember to delete[] it) + */ +char * ShaderProgram::GetShaderSource(const char * src_file) const +{ + char * src = NULL; + FILE * file = fopen(src_file, "r"); + if (file == NULL) + { + Error("Could not open shader source file \"%s\": %s", src_file, strerror(errno)); + return NULL; + } + long start = ftell(file); + + if (fseek(file, 0, SEEK_END) != 0) + { + Error("Couldn't seek to end of file \"%s\": %s", src_file, strerror(errno)); + return NULL; + } + long end = ftell(file); + if (start < 0 || end < 0 || end < start) + { + // I bet that now I've put this message here, it will occur at least once in the life of this code + Error("Insane results from ftell(3) on file \"%s\"", src_file); + return NULL; + } + size_t size = end - start; + src = new char[size+1]; // Warning! Allocation of memory occuring! We might all die! + rewind(file); + if (fread(src, 1,size, file) != size) + { + Error("Error in fread on \"%s\": %s", src_file, strerror(errno)); + fclose(file); + delete [] src; + return NULL; + } + src[size] = '\0'; + fclose(file); + return src; + +} + +bool ShaderProgram::AttachShader(const char * src_file, GLenum type) { GLuint shader_obj = glCreateShader(type); + char * src = GetShaderSource(src_file); + if (src == NULL) + { + Error("Couldn't get shader source."); + return false; + } + + glShaderSource(shader_obj, 1, &src, 0); glCompileShader(shader_obj); int did_compile = 0; glGetShaderiv(shader_obj, GL_COMPILE_STATUS, &did_compile); + delete [] src; // Oh my goodness memory management is hard guys if (!did_compile) { char info_log[2048]; glGetShaderInfoLog(shader_obj, 2048, nullptr, info_log); - Error("Shader compile error: %s\n", info_log); + Error("Shader compile error (file \"%s\"): %s (type %d)", src_file, info_log, type); return false; } m_shaders.push_back(Shader{type, shader_obj}); - LazyCreateProgram(); + LazyCreateProgram(); // um... why? glAttachShader(m_program, shader_obj); return true; } -bool ShaderProgram::AttachVertexProgram(const char *src) -{ - return AttachShader(src, GL_VERTEX_SHADER); -} - -bool ShaderProgram::AttachFragmentProgram(const char *src) -{ - return AttachShader(src, GL_FRAGMENT_SHADER); -} - -bool ShaderProgram::AttachGeometryProgram(const char *src) -{ - return AttachShader(src, GL_GEOMETRY_SHADER); -} bool ShaderProgram::Link() { diff --git a/src/shaderprogram.h b/src/shaderprogram.h index c052566..9cedab6 100644 --- a/src/shaderprogram.h +++ b/src/shaderprogram.h @@ -7,18 +7,27 @@ namespace IPDF { - /* - * The "Shader" class represents a GLSL program made from shaders. + /** + * The "Shader" class represents a GLSL program made from shaders. */ class ShaderProgram { public: ShaderProgram() : m_program(0) {} ~ShaderProgram(); - bool AttachVertexProgram(const char *src); - bool AttachFragmentProgram(const char *src); - bool AttachGeometryProgram(const char *src); - bool Link(); + + inline bool AttachGeometryProgram(const char * geometry_file) {return AttachShader(geometry_file, GL_GEOMETRY_SHADER);} + inline bool AttachVertexProgram(const char * vertex_file) {return AttachShader(vertex_file, GL_VERTEX_SHADER);} + inline bool AttachFragmentProgram(const char * fragment_file) {return AttachShader(fragment_file, GL_FRAGMENT_SHADER);} + + /** Read shaders from files and attach them + * @returns false if any of the shaders cannot be attached + */ + inline bool AttachShaderPrograms(const char * geometry_file, const char * vertex_file, const char * fragment_file) + { + return AttachGeometryProgram(geometry_file) && AttachVertexProgram(vertex_file) && AttachFragmentProgram(fragment_file); + } + bool Link(); // currently always returns true? const void Use() const; // Unfortunately, we don't require GL 4.3/ARB_explicit_uniform_location // which would make this obsolete. One uday Mesa will support it. @@ -26,9 +35,12 @@ namespace IPDF // Mesa supports ARB_shading_language_420pack, but that'd be a bit more // work right with the way some of our uniforms are laid out at the moment. const GLint GetUniformLocation(const char *uniform_name) const; + private: void LazyCreateProgram(); - bool AttachShader(const char *src, GLenum type); + /** Read shader source from src_file and attach it as type **/ + bool AttachShader(const char * src_file, GLenum type); + char * GetShaderSource(const char * src_file) const; GLuint m_program; struct Shader { diff --git a/src/shaders/basictex_frag.glsl b/src/shaders/basictex_frag.glsl new file mode 100644 index 0000000..534ff02 --- /dev/null +++ b/src/shaders/basictex_frag.glsl @@ -0,0 +1,15 @@ +#version 140 + +in vec2 fp_tex_coord; + +out vec4 output_colour; + +uniform sampler2D tex; +uniform vec4 colour; + +void main() +{ + output_colour = colour; + output_colour.a = texture(tex, fp_tex_coord).r; +} + diff --git a/src/shaders/basictex_vert.glsl b/src/shaders/basictex_vert.glsl new file mode 100644 index 0000000..1b65864 --- /dev/null +++ b/src/shaders/basictex_vert.glsl @@ -0,0 +1,25 @@ +#version 140 +#extension GL_ARB_shading_language_420pack : require +#extension GL_ARB_explicit_attrib_location : require + +layout(std140, binding=0) uniform Viewport +{ + float width; + float height; +}; + +layout(location = 0) in vec2 position; +layout(location = 1) in vec2 tex_coord; + +out vec2 fp_tex_coord; + +void main() +{ + // Transform to clip coordinates (-1,1, -1,1). + gl_Position.x = (position.x*2/width) - 1; + gl_Position.y = 1 - (position.y*2/height); + gl_Position.z = 0.0; + gl_Position.w = 1.0; + fp_tex_coord = tex_coord; +} + diff --git a/src/shaders/circle_filled_geom.glsl b/src/shaders/circle_filled_geom.glsl new file mode 100644 index 0000000..c9f54da --- /dev/null +++ b/src/shaders/circle_filled_geom.glsl @@ -0,0 +1,22 @@ +#version 150 + +layout(lines) in; +layout(triangle_strip, max_vertices = 4) out; +out vec2 objcoords; + +void main() +{ + gl_Position = gl_in[0].gl_Position; + objcoords = vec2(-1.0, -1.0); + EmitVertex(); + gl_Position = vec4(gl_in[0].gl_Position.x, gl_in[1].gl_Position.y, 0.0, 1.0); + objcoords = vec2(-1.0, 1.0); + EmitVertex(); + gl_Position = vec4(gl_in[1].gl_Position.x, gl_in[0].gl_Position.y, 0.0, 1.0); + objcoords = vec2(1.0, -1.0); + EmitVertex(); + gl_Position = gl_in[1].gl_Position; + objcoords = vec2(1.0, 1.0); + EmitVertex(); + EndPrimitive(); +} diff --git a/src/shaders/circle_frag.glsl b/src/shaders/circle_frag.glsl new file mode 100644 index 0000000..b4fab10 Binary files /dev/null and b/src/shaders/circle_frag.glsl differ diff --git a/src/shaders/rect_filled_geom.glsl b/src/shaders/rect_filled_geom.glsl new file mode 100644 index 0000000..2793ab7 --- /dev/null +++ b/src/shaders/rect_filled_geom.glsl @@ -0,0 +1,17 @@ +#version 150 + +layout(lines) in; +layout(triangle_strip, max_vertices = 4) out; + +void main() +{ + gl_Position = gl_in[0].gl_Position; + EmitVertex(); + gl_Position = vec4(gl_in[0].gl_Position.x, gl_in[1].gl_Position.y, 0.0, 1.0); + EmitVertex(); + gl_Position = vec4(gl_in[1].gl_Position.x, gl_in[0].gl_Position.y, 0.0, 1.0); + EmitVertex(); + gl_Position = gl_in[1].gl_Position; + EmitVertex(); + EndPrimitive(); +} diff --git a/src/shaders/rect_frag.glsl b/src/shaders/rect_frag.glsl new file mode 100644 index 0000000..649805f --- /dev/null +++ b/src/shaders/rect_frag.glsl @@ -0,0 +1,10 @@ +#version 140 + +out vec4 output_colour; + +uniform vec4 colour; + +void main() +{ + output_colour = colour; +} diff --git a/src/shaders/rect_outline_geom.glsl b/src/shaders/rect_outline_geom.glsl new file mode 100644 index 0000000..20ad319 --- /dev/null +++ b/src/shaders/rect_outline_geom.glsl @@ -0,0 +1,20 @@ +#version 150 + +layout(lines) in; +layout(line_strip, max_vertices = 5) out; + +void main() +{ + gl_Position = gl_in[0].gl_Position; + EmitVertex(); + gl_Position = vec4(gl_in[0].gl_Position.x, gl_in[1].gl_Position.y, 0.0, 1.0); + EmitVertex(); + gl_Position = gl_in[1].gl_Position; + EmitVertex(); + gl_Position = vec4(gl_in[1].gl_Position.x, gl_in[0].gl_Position.y, 0.0, 1.0); + EmitVertex(); + gl_Position = gl_in[0].gl_Position; + EmitVertex(); + EndPrimitive(); +} + diff --git a/src/shaders/rect_vert.glsl b/src/shaders/rect_vert.glsl new file mode 100644 index 0000000..cc15e56 --- /dev/null +++ b/src/shaders/rect_vert.glsl @@ -0,0 +1,25 @@ +#version 140 +#extension GL_ARB_shading_language_420pack : require +#extension GL_ARB_explicit_attrib_location : require + +layout(std140, binding=0) uniform ViewBounds +{ + float bounds_x; + float bounds_y; + float bounds_w; + float bounds_h; +}; + +layout(location = 0) in vec2 position; + +void main() +{ + vec2 transformed_position; + transformed_position.x = (position.x - bounds_x) / bounds_w; + transformed_position.y = (position.y - bounds_y) / bounds_h; + // Transform to clip coordinates (-1,1, -1,1). + gl_Position.x = (transformed_position.x*2) - 1; + gl_Position.y = 1 - (transformed_position.y*2); + gl_Position.z = 0.0; + gl_Position.w = 1.0; +} diff --git a/src/tests/bezier.cpp b/src/tests/bezier.cpp index 1e68ec2..ea0389c 100644 --- a/src/tests/bezier.cpp +++ b/src/tests/bezier.cpp @@ -8,7 +8,7 @@ #include // hashtable #include #include "screen.h" -#include + #include "pointstobitmap.h" using namespace std; diff --git a/src/tests/lines.cpp b/src/tests/lines.cpp new file mode 100644 index 0000000..b15d218 --- /dev/null +++ b/src/tests/lines.cpp @@ -0,0 +1,76 @@ +#include "main.h" + +#include "pointstobitmap.h" + +using namespace std; + +/** + * NOTE: I am using vector > because it is convenient; don't have to round to pixels, can print to stdout and gnuplot, etc + * vector > should obviously not be used in a practical implementation; directly access the pixel buffer + */ + +template vector > LineDDA(const T & x1, const T & y1, const T & x2, const T & y2) +{ + T dx = x2 - x1; + T dy = y2 - y1; + uint64_t steps = lround(max(abs(dx), abs(dy))); + T xInc = T(dx)/T(steps); + T yInc = T(dy)/T(steps); + T x = x1; T y = y1; + vector > result(steps); + for (uint64_t k = 0; k <= steps; ++k) + { + result[k] = pair(round(x), round(y)); + x += xInc; + y += yInc; + } + return result; +} +/** + * Only works for 0 < m < 1 + */ +template vector > LineBresenham(const T & x1, const T & y1, const T & x2, const T & y2) +{ + T dx = abs(x2 - x1); + T dy = abs(y2 - y1); + T p = 2*dy - dx; + T two_dy = 2*dy; + T two_dxdy = 2*(dy-dx); + + T x; T y; T xEnd; + if (x1 > x2) + { + x = x2; + y = y2; + xEnd = x1; + } + else + { + x = x1; + y = y1; + xEnd = x2; + } + vector > result; + while (x < xEnd) + { + x += 1; + if (p < 0) + p += two_dy; + else + { + y += 1; + p += two_dxdy; + } + result.emplace_back(pair(x,y)); + } + return result; +} + +int main(int argc, char ** argv) +{ + auto f = LineDDA(0,0,400,200); + PointsToBitmap(f, 1, 0,0,0,"lines.bmp"); + auto i = LineBresenham(0,100,400,300); + i.push_back(pair(0,0)); + PointsToBitmap(i, 1, 255,0,0,"lines.bmp", true); +} diff --git a/src/tests/pointstobitmap.h b/src/tests/pointstobitmap.h index 90bfbdb..36db365 100644 --- a/src/tests/pointstobitmap.h +++ b/src/tests/pointstobitmap.h @@ -2,6 +2,22 @@ #define _POINTSTOBITMAP_H #include +#include // for min/max_element + +void AntiAlias(unsigned char * pixels, uint64_t w, uint64_t h, uint8_t stride = 4) +{ + int ri = (SDL_BYTEORDER == SDL_LIL_ENDIAN) ? 0 : 3; + int gi = (SDL_BYTEORDER == SDL_LIL_ENDIAN) ? 1 : 2; + int bi = (SDL_BYTEORDER == SDL_LIL_ENDIAN) ? 2 : 1; + for (uint64_t x = 1; x < w-1; ++x) + { + for (uint64_t y = 1; y < h-1; ++y) + { + uint64_t index = stride*(y*w + x); + + } + } +} /** * Map vector of points onto a Bitmap @@ -60,7 +76,16 @@ template void PointsToBitmap(const vector > & points, const pair min(left.first, bottom.second); pair max(right.first, top.second); - + // Force to be square + if (max.first - min.first > max.second - min.second) + { + max.second = min.second + (max.first - min.first); + } + else + { + max.first = min.first + (max.second - min.second); + } + Debug("Bitmap: %llf %llf -> %llf %llf", min.first, min.second, max.first, max.second); // Alternately, just do this: /* pair min(-scale, -scale); diff --git a/src/tests/represent.cpp b/src/tests/represent.cpp index c576802..b893f97 100644 --- a/src/tests/represent.cpp +++ b/src/tests/represent.cpp @@ -242,14 +242,14 @@ int main(int argc, char ** argv) printf("# Convert custom floats to a Real\n"); printf("# a\thex(a)\tReal(a)\tdelta(last2)\n"); - typedef uint16_t Bits; + typedef uint8_t Bits; typedef pair Pear; - const uint8_t E = 5; - const uint8_t P = 10; + const uint8_t E = 3; + const uint8_t P = 4; list space; - Bits a0 = 0x0000; - for (Bits a = a0; a < 0xFFFF; ++a) + Bits a0 = 0x00; + for (Bits a = a0; a < 0xFF; ++a) { Real x = BitsToReal(&a); Bits b = 0; BitsFromReal(x, &b); @@ -274,4 +274,4 @@ int main(int argc, char ** argv) //0|011 11|00 0000 0001 -//0|000 01|00 0000 0000 \ No newline at end of file +//0|000 01|00 0000 0000 diff --git a/src/view.cpp b/src/view.cpp index a92da9b..fd26b13 100644 --- a/src/view.cpp +++ b/src/view.cpp @@ -5,125 +5,12 @@ using namespace IPDF; using namespace std; -#define RECT_VERT \ - "#version 140\n"\ - "#extension GL_ARB_shading_language_420pack : require\n"\ - "#extension GL_ARB_explicit_attrib_location : require\n"\ - "\n"\ - "layout(std140, binding=0) uniform ViewBounds\n"\ - "{\n"\ - "\tfloat bounds_x;\n"\ - "\tfloat bounds_y;\n"\ - "\tfloat bounds_w;\n"\ - "\tfloat bounds_h;\n"\ - "};\n"\ - "\n"\ - "layout(location = 0) in vec2 position;\n"\ - "\n"\ - "void main()\n"\ - "{\n"\ - "\tvec2 transformed_position;\n"\ - "\ttransformed_position.x = (position.x - bounds_x) / bounds_w;\n"\ - "\ttransformed_position.y = (position.y - bounds_y) / bounds_h;\n"\ - "\t// Transform to clip coordinates (-1,1, -1,1).\n"\ - "\tgl_Position.x = (transformed_position.x*2) - 1;\n"\ - "\tgl_Position.y = 1 - (transformed_position.y*2);\n"\ - "\tgl_Position.z = 0.0;\n"\ - "\tgl_Position.w = 1.0;\n"\ - "}\n" - -#define RECT_FRAG \ - "#version 140\n"\ - "\n"\ - "out vec4 output_colour;\n"\ - "\n"\ - "uniform vec4 colour;\n"\ - "\n"\ - "void main()\n"\ - "{\n"\ - "\toutput_colour = colour;\n"\ - "}\n" - -#define RECT_OUTLINE_GEOM \ - "#version 150\n"\ - "\n"\ - "layout(lines) in;\n"\ - "layout(line_strip, max_vertices = 5) out;\n"\ - "\n"\ - "void main()\n"\ - "{\n"\ - "\tgl_Position = gl_in[0].gl_Position;\n"\ - "\tEmitVertex();\n"\ - "\tgl_Position = vec4(gl_in[0].gl_Position.x, gl_in[1].gl_Position.y, 0.0, 1.0);\n"\ - "\tEmitVertex();\n"\ - "\tgl_Position = gl_in[1].gl_Position;\n"\ - "\tEmitVertex();\n"\ - "\tgl_Position = vec4(gl_in[1].gl_Position.x, gl_in[0].gl_Position.y, 0.0, 1.0);\n"\ - "\tEmitVertex();\n"\ - "\tgl_Position = gl_in[0].gl_Position;\n"\ - "\tEmitVertex();\n"\ - "\tEndPrimitive();\n"\ - "}\n" - -#define RECT_FILLED_GEOM \ - "#version 150\n"\ - "\n"\ - "layout(lines) in;\n"\ - "layout(triangle_strip, max_vertices = 4) out;\n"\ - "\n"\ - "void main()\n"\ - "{\n"\ - "\tgl_Position = gl_in[0].gl_Position;\n"\ - "\tEmitVertex();\n"\ - "\tgl_Position = vec4(gl_in[0].gl_Position.x, gl_in[1].gl_Position.y, 0.0, 1.0);\n"\ - "\tEmitVertex();\n"\ - "\tgl_Position = vec4(gl_in[1].gl_Position.x, gl_in[0].gl_Position.y, 0.0, 1.0);\n"\ - "\tEmitVertex();\n"\ - "\tgl_Position = gl_in[1].gl_Position;\n"\ - "\tEmitVertex();\n"\ - "\tEndPrimitive();\n"\ - "}\n" - -#define CIRCLE_FILLED_GEOM \ - "#version 150\n"\ - "\n"\ - "layout(lines) in;\n"\ - "layout(triangle_strip, max_vertices = 4) out;\n"\ - "out vec2 objcoords;\n"\ - "\n"\ - "void main()\n"\ - "{\n"\ - "\tgl_Position = gl_in[0].gl_Position;\n"\ - "\tobjcoords = vec2(-1.0, -1.0);\n"\ - "\tEmitVertex();\n"\ - "\tgl_Position = vec4(gl_in[0].gl_Position.x, gl_in[1].gl_Position.y, 0.0, 1.0);\n"\ - "\tobjcoords = vec2(-1.0, 1.0);\n"\ - "\tEmitVertex();\n"\ - "\tgl_Position = vec4(gl_in[1].gl_Position.x, gl_in[0].gl_Position.y, 0.0, 1.0);\n"\ - "\tobjcoords = vec2(1.0, -1.0);\n"\ - "\tEmitVertex();\n"\ - "\tgl_Position = gl_in[1].gl_Position;\n"\ - "\tobjcoords = vec2(1.0, 1.0);\n"\ - "\tEmitVertex();\n"\ - "\tEndPrimitive();\n"\ - "}\n" - -#define CIRCLE_FRAG \ - "#version 140\n"\ - "\n"\ - "in vec2 objcoords;\n"\ - "out vec4 output_colour;\n"\ - "\n"\ - "uniform vec4 colour;\n"\ - "\n"\ - "void main()\n"\ - "{\n"\ - "\tif ((objcoords.x)*(objcoords.x) + (objcoords.y)*(objcoords.y) > 1.0)\n"\ - "\t{\n"\ - "\t\tdiscard;\n"\ - "\t}\n"\ - "\toutput_colour = colour;\n"\ - "}\n" +#define RECT_VERT "shaders/rect_vert.glsl" +#define RECT_FRAG "shaders/rect_frag.glsl" +#define RECT_OUTLINE_GEOM "shaders/rect_outline_geom.glsl" +#define RECT_FILLED_GEOM "shaders/rect_filled_geom.glsl" +#define CIRCLE_FILLED_GEOM "shaders/circle_filled_geom.glsl" +#define CIRCLE_FRAG "shaders/circle_frag.glsl" void View::Translate(Real x, Real y) { @@ -327,23 +214,18 @@ void View::UpdateObjBoundsVBO() void View::PrepareRender() { // TODO: Error check here. - m_rect_outline_shader.AttachGeometryProgram(RECT_OUTLINE_GEOM); - m_rect_outline_shader.AttachVertexProgram(RECT_VERT); - m_rect_outline_shader.AttachFragmentProgram(RECT_FRAG); + + m_rect_outline_shader.AttachShaderPrograms(RECT_OUTLINE_GEOM, RECT_VERT, RECT_FRAG); m_rect_outline_shader.Link(); m_rect_outline_shader.Use(); glUniform4f(m_rect_outline_shader.GetUniformLocation("colour"), m_colour.r, m_colour.g, m_colour.b, m_colour.a); - m_rect_filled_shader.AttachGeometryProgram(RECT_FILLED_GEOM); - m_rect_filled_shader.AttachVertexProgram(RECT_VERT); - m_rect_filled_shader.AttachFragmentProgram(RECT_FRAG); + m_rect_filled_shader.AttachShaderPrograms(RECT_FILLED_GEOM, RECT_VERT, RECT_FRAG); m_rect_filled_shader.Link(); m_rect_filled_shader.Use(); glUniform4f(m_rect_filled_shader.GetUniformLocation("colour"), m_colour.r, m_colour.g, m_colour.b, m_colour.a); - m_circle_filled_shader.AttachGeometryProgram(CIRCLE_FILLED_GEOM); - m_circle_filled_shader.AttachVertexProgram(RECT_VERT); - m_circle_filled_shader.AttachFragmentProgram(CIRCLE_FRAG); + m_circle_filled_shader.AttachShaderPrograms(CIRCLE_FILLED_GEOM, RECT_VERT, CIRCLE_FRAG); m_circle_filled_shader.Link(); m_circle_filled_shader.Use(); glUniform4f(m_circle_filled_shader.GetUniformLocation("colour"), m_colour.r, m_colour.g, m_colour.b, m_colour.a);