So we can edit them without going insane.
#include <cstdio>
#include <cstdlib>
#include <string>
+#include <cstring> // for strerror etc
inline std::string methodName(const std::string& prettyFunction)
{
#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;
glDeleteProgram(m_program);
}
+/**
+ * This is only called once, does it need a function?
+ */
void ShaderProgram::LazyCreateProgram()
{
if (!m_program)
}
}
-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()
{
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.
// 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
{
--- /dev/null
+#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;
+}
+
--- /dev/null
+#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;
+}
+
--- /dev/null
+#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();
+}
--- /dev/null
+#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();
+}
--- /dev/null
+#version 140
+
+out vec4 output_colour;
+
+uniform vec4 colour;
+
+void main()
+{
+ output_colour = colour;
+}
--- /dev/null
+#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();
+}
+
--- /dev/null
+#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;
+}
#include <unordered_map> // hashtable
#include <map>
#include "screen.h"
-#include <algorithm>
+
#include "pointstobitmap.h"
using namespace std;
--- /dev/null
+#include "main.h"
+
+#include "pointstobitmap.h"
+
+using namespace std;
+
+/**
+ * NOTE: I am using vector<pair<T,T> > because it is convenient; don't have to round to pixels, can print to stdout and gnuplot, etc
+ * vector<pair<T,T> > should obviously not be used in a practical implementation; directly access the pixel buffer
+ */
+
+template <class T> vector<pair<T, T> > 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<pair<T,T> > result(steps);
+ for (uint64_t k = 0; k <= steps; ++k)
+ {
+ result[k] = pair<T,T>(round(x), round(y));
+ x += xInc;
+ y += yInc;
+ }
+ return result;
+}
+/**
+ * Only works for 0 < m < 1
+ */
+template <class T> vector<pair<T, T> > 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<pair<T,T> > result;
+ while (x < xEnd)
+ {
+ x += 1;
+ if (p < 0)
+ p += two_dy;
+ else
+ {
+ y += 1;
+ p += two_dxdy;
+ }
+ result.emplace_back(pair<T,T>(x,y));
+ }
+ return result;
+}
+
+int main(int argc, char ** argv)
+{
+ auto f = LineDDA<float>(0,0,400,200);
+ PointsToBitmap<float>(f, 1, 0,0,0,"lines.bmp");
+ auto i = LineBresenham<int>(0,100,400,300);
+ i.push_back(pair<int,int>(0,0));
+ PointsToBitmap<int>(i, 1, 255,0,0,"lines.bmp", true);
+}
#define _POINTSTOBITMAP_H
#include <SDL.h>
+#include <algorithm> // 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
pair<LD,LD> min(left.first, bottom.second);
pair<LD,LD> 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<LD,LD> min(-scale, -scale);
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<Bits, Real> Pear;
- const uint8_t E = 5;
- const uint8_t P = 10;
+ const uint8_t E = 3;
+ const uint8_t P = 4;
list<Pear> space;
- Bits a0 = 0x0000;
- for (Bits a = a0; a < 0xFFFF; ++a)
+ Bits a0 = 0x00;
+ for (Bits a = a0; a < 0xFF; ++a)
{
Real x = BitsToReal<E,P>(&a);
Bits b = 0; BitsFromReal<E,P>(x, &b);
//0|011 11|00 0000 0001
-//0|000 01|00 0000 0000
\ No newline at end of file
+//0|000 01|00 0000 0000
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)
{
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);