# HG changeset patch # User John Tsiombikas # Date 1398603767 -10800 # Node ID 4abdce1361b96b97215aec93a8f80e8761b8db13 initial commit diff -r 000000000000 -r 4abdce1361b9 erebus.sln --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/erebus.sln Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,39 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "erebus", "erebus.vcxproj", "{55E5C1D8-DF5A-4380-A77F-4D317165E7BB}" + ProjectSection(ProjectDependencies) = postProject + {6172E997-FB04-4DB6-A1CC-20135451E62B} = {6172E997-FB04-4DB6-A1CC-20135451E62B} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liberebus", "liberebus\liberebus.vcxproj", "{6172E997-FB04-4DB6-A1CC-20135451E62B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {55E5C1D8-DF5A-4380-A77F-4D317165E7BB}.Debug|Win32.ActiveCfg = Debug|Win32 + {55E5C1D8-DF5A-4380-A77F-4D317165E7BB}.Debug|Win32.Build.0 = Debug|Win32 + {55E5C1D8-DF5A-4380-A77F-4D317165E7BB}.Debug|x64.ActiveCfg = Debug|x64 + {55E5C1D8-DF5A-4380-A77F-4D317165E7BB}.Debug|x64.Build.0 = Debug|x64 + {55E5C1D8-DF5A-4380-A77F-4D317165E7BB}.Release|Win32.ActiveCfg = Release|Win32 + {55E5C1D8-DF5A-4380-A77F-4D317165E7BB}.Release|Win32.Build.0 = Release|Win32 + {55E5C1D8-DF5A-4380-A77F-4D317165E7BB}.Release|x64.ActiveCfg = Release|x64 + {55E5C1D8-DF5A-4380-A77F-4D317165E7BB}.Release|x64.Build.0 = Release|x64 + {6172E997-FB04-4DB6-A1CC-20135451E62B}.Debug|Win32.ActiveCfg = Debug|Win32 + {6172E997-FB04-4DB6-A1CC-20135451E62B}.Debug|Win32.Build.0 = Debug|Win32 + {6172E997-FB04-4DB6-A1CC-20135451E62B}.Debug|x64.ActiveCfg = Debug|Win32 + {6172E997-FB04-4DB6-A1CC-20135451E62B}.Release|Win32.ActiveCfg = Release|Win32 + {6172E997-FB04-4DB6-A1CC-20135451E62B}.Release|Win32.Build.0 = Release|Win32 + {6172E997-FB04-4DB6-A1CC-20135451E62B}.Release|x64.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff -r 000000000000 -r 4abdce1361b9 erebus.vcxproj --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/erebus.vcxproj Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,163 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + + + {55E5C1D8-DF5A-4380-A77F-4D317165E7BB} + Win32Proj + erebus + + + + Application + true + v120 + Unicode + + + Application + true + v120 + Unicode + + + Application + false + v120 + true + Unicode + + + Application + false + v120 + true + Unicode + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + 4244;4305;4996 + + + Console + true + opengl32.lib;glut32.lib;glew32.lib;libvmath.lib;libimago2.lib;jpeglib.lib;libpng.lib;zlib.lib;liberebus.lib;%(AdditionalDependencies) + $(SolutionDir)\liberebus\$(Configuration);%(AdditionalLibraryDirectories) + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + 4244;4305;4996 + + + Console + true + opengl32.lib;glut32.lib;glew32.lib;libvmath.lib;libimago2.lib;jpeglib.lib;libpng.lib;zlib.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + 4244;4305;4996 + + + Console + true + true + true + opengl32.lib;glut32.lib;glew32.lib;libvmath.lib;libimago2.lib;jpeglib.lib;libpng.lib;zlib.lib;liberebus.lib;%(AdditionalDependencies) + $(SolutionDir)\liberebus\$(Configuration);%(AdditionalLibraryDirectories) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + 4244;4305;4996 + + + Console + true + true + true + opengl32.lib;glut32.lib;glew32.lib;libvmath.lib;libimago2.lib;jpeglib.lib;libpng.lib;zlib.lib;%(AdditionalDependencies) + + + + + + \ No newline at end of file diff -r 000000000000 -r 4abdce1361b9 erebus.vcxproj.filters --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/erebus.vcxproj.filters Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,36 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + \ No newline at end of file diff -r 000000000000 -r 4abdce1361b9 liberebus/liberebus.vcxproj --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liberebus/liberebus.vcxproj Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,102 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + + + + + + + + + + + + + + + + + + + + + {6172E997-FB04-4DB6-A1CC-20135451E62B} + Win32Proj + liberebus + + + + StaticLibrary + true + v120 + Unicode + + + StaticLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + 4244 + + + Windows + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + 4244 + + + Windows + true + true + true + + + + + + \ No newline at end of file diff -r 000000000000 -r 4abdce1361b9 liberebus/liberebus.vcxproj.filters --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liberebus/liberebus.vcxproj.filters Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,77 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff -r 000000000000 -r 4abdce1361b9 liberebus/src/brdf.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liberebus/src/brdf.cc Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,130 @@ +#include "brdf.h" +#include "erebus_impl.h" + +ReflAttrib::ReflAttrib() + : value(1), color(1, 1, 1), map(0) +{ +} + +ReflAttrib::ReflAttrib(const Color &col, Texture *tex) +{ + set_color(col); + map = tex; +} + +void ReflAttrib::set_value(float val) +{ + value = val; + color = Color{val, val, val}; +} + +void ReflAttrib::set_color(const Color &col) +{ + color = col; + value = color_luminance(col); +} + +void ReflAttrib::set_map(Texture *tex) +{ + map = tex; +} + +Texture *ReflAttrib::get_map() const +{ + return map; +} + +float ReflAttrib::get_value() const +{ + return value; +} + +float ReflAttrib::get_value(float u, float v) const +{ + return map ? value * color_luminance(map->lookup(u, v)) : value; +} + +const Color &ReflAttrib::get_color() const +{ + return color; +} + +Color ReflAttrib::get_color(float u, float v) const +{ + return map ? color * map->lookup(u, v) : color; +} + +// ---- class Reflectance ---- +ReflAttrib Reflectance::def_attrib; + +Reflectance::Reflectance() +{ + set_default_attribs(); +} + +void Reflectance::set_attrib(const char *name, const Color &color, Texture *tex) +{ + attrib[name] = ReflAttrib{color, tex}; +} + +ReflAttrib &Reflectance::get_attrib(const char *name) +{ + auto it = attrib.find(name); + if(it == attrib.end()) { + return def_attrib; + } + return it->second; +} + +const ReflAttrib &Reflectance::get_attrib(const char *name) const +{ + auto it = attrib.find(name); + if(it == attrib.end()) { + return def_attrib; + } + return it->second; +} + +float Reflectance::get_attrib_value(const char *name) const +{ + return get_attrib(name).get_value(); +} + +float Reflectance::get_attrib_value(const char *name, float u, float v) const +{ + return get_attrib(name).get_value(u, v); +} + +Color Reflectance::get_attrib_color(const char *name) const +{ + return get_attrib(name).get_color(); +} + +Color Reflectance::get_attrib_color(const char *name, float u, float v) const +{ + return get_attrib(name).get_color(u, v); +} + +float Reflectance::sample(const Vector3 &norm, const Vector3 &outdir, Vector3 *indir) const +{ + *indir = sample_dir(norm, outdir); + return eval(norm, outdir, *indir); +} + +// --- class LambertRefl --- + +void LambertRefl::set_default_attribs() +{ + set_attrib("color", Color(1, 1, 1)); +} + +Vector3 LambertRefl::sample_dir(const Vector3 &norm, const Vector3 &outdir) const +{ + Vector3 dir = Vector3{randf(-1, 1), randf(-1, 1), randf(-1, 1)}.normalized(); + return dot_product(dir, norm) < 0.0 ? -dir : dir; +} + +float LambertRefl::eval(const Vector3 &norm, const Vector3 &outdir, const Vector3 &indir) const +{ + return dot_product(norm, outdir); +} \ No newline at end of file diff -r 000000000000 -r 4abdce1361b9 liberebus/src/brdf.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liberebus/src/brdf.h Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,67 @@ +#ifndef BRDF_H_ +#define BRDF_H_ + +#include +#include +#include "color.h" +#include "texture.h" + +class ReflAttrib { +private: + float value; + Color color; + Texture *map; + +public: + + ReflAttrib(); + explicit ReflAttrib(const Color &color, Texture *tex = 0); + + void set_value(float val); + void set_color(const Color &col); + + void set_map(Texture *tex); + Texture *get_map() const; + + float get_value() const; + float get_value(float u, float v) const; + const Color &get_color() const; + Color get_color(float u, float v) const; +}; + + +class Reflectance { +private: + static ReflAttrib def_attrib; + std::map attrib; + + virtual void set_default_attribs(); + +public: + Reflectance(); + virtual ~Reflectance() = default; + + virtual void set_attrib(const char *name, const Color &color, Texture *tex = 0); + virtual ReflAttrib &get_attrib(const char *name); + virtual const ReflAttrib &get_attrib(const char *name) const; + + virtual float get_attrib_value(const char *name) const; + virtual float get_attrib_value(const char *name, float u, float v) const; + virtual Color get_attrib_color(const char *name) const; + virtual Color get_attrib_color(const char *name, float u, float v) const; + + virtual Vector3 sample_dir(const Vector3 &norm, const Vector3 &outdir) const = 0; + virtual float sample(const Vector3 &norm, const Vector3 &outdir, Vector3 *indir) const; + virtual float eval(const Vector3 &norm, const Vector3 &outdir, const Vector3 &indir) const = 0; +}; + +class LambertRefl : public Reflectance { +private: + void set_default_attribs() override; + +public: + Vector3 sample_dir(const Vector3 &norm, const Vector3 &outdir) const override; + float eval(const Vector3 &norm, const Vector3 &outdir, const Vector3 &indir) const override; +}; + +#endif // BRDF_H_ \ No newline at end of file diff -r 000000000000 -r 4abdce1361b9 liberebus/src/bvol.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liberebus/src/bvol.cc Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,38 @@ +#include "bvol.h" + +bool AABox::intersect(const Ray &ray) const +{ + Vector3 param[2] = {vmin, vmax}; + Vector3 inv_dir(1.0 / ray.dir.x, 1.0 / ray.dir.y, 1.0 / ray.dir.z); + int sign[3] = {inv_dir.x < 0, inv_dir.y < 0, inv_dir.z < 0}; + + float tmin = (param[sign[0]].x - ray.origin.x) * inv_dir.x; + float tmax = (param[1 - sign[0]].x - ray.origin.x) * inv_dir.x; + float tymin = (param[sign[1]].y - ray.origin.y) * inv_dir.y; + float tymax = (param[1 - sign[1]].y - ray.origin.y) * inv_dir.y; + + if(tmin > tymax || tymin > tmax) { + return false; + } + if(tymin > tmin) { + tmin = tymin; + } + if(tymax < tmax) { + tmax = tymax; + } + + float tzmin = (param[sign[2]].z - ray.origin.z) * inv_dir.z; + float tzmax = (param[1 - sign[2]].z - ray.origin.z) * inv_dir.z; + + if(tmin > tzmax || tzmin > tmax) { + return false; + } + if(tzmin > tmin) { + tmin = tzmin; + } + if(tzmax < tmax) { + tmax = tzmax; + } + + return true; +} \ No newline at end of file diff -r 000000000000 -r 4abdce1361b9 liberebus/src/bvol.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liberebus/src/bvol.h Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,16 @@ +#ifndef BVOL_H_ +#define BVOL_H_ + +#include "vmath/ray.h" + +class AABox { +public: + Vector3 vmin, vmax; + + AABox() : vmin(-0.5, -0.5, -0.5), vmax(0.5, 0.5, 0.5) {} + AABox(const Vector3 &v0, const Vector3 &v1) : vmin(v0), vmax(v1) {} + + bool intersect(const Ray &ray) const; +}; + +#endif // BVOL_H_ \ No newline at end of file diff -r 000000000000 -r 4abdce1361b9 liberebus/src/camera.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liberebus/src/camera.cc Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,207 @@ +#include +#include +#include "camera.h" + +static void calc_sample_pos_rec(int sidx, float xsz, float ysz, float *pos); + +Camera::Camera() +{ + vfov = M_PI / 4.0; + cached_matrix_valid = false; + + rdir_cache_width = rdir_cache_height = 0; + rdir_cache = 0; +} + +Camera::Camera(const Vector3 &p) + : pos(p) +{ + vfov = M_PI / 4.0; + cached_matrix_valid = false; + + rdir_cache_width = rdir_cache_height = 0; + rdir_cache = 0; +} + +Camera::~Camera() +{ + delete [] rdir_cache; +} + +void Camera::set_fov(float vfov) +{ + this->vfov = vfov; + + // invalidate the dir cache + delete [] rdir_cache; +} + +float Camera::get_fov() const +{ + return vfov; +} + +void Camera::set_position(const Vector3 &pos) +{ + this->pos = pos; + cached_matrix_valid = false; // invalidate the cached matrix +} + +const Vector3 &Camera::get_position() const +{ + return pos; +} + +const Matrix4x4 &Camera::get_matrix() const +{ + if(!cached_matrix_valid) { + calc_matrix(&cached_matrix); + cached_matrix_valid = true; + } + return cached_matrix; +} + +Vector2 Camera::calc_sample_pos(int x, int y, int xsz, int ysz, int sample) const +{ + float ppos[2]; + float aspect = (float)xsz / (float)ysz; + + float pwidth = 2.0 * aspect / (float)xsz; + float pheight = 2.0 / (float)ysz; + + ppos[0] = (float)x * pwidth - aspect; + ppos[1] = 1.0 - (float)y * pheight; + + calc_sample_pos_rec(sample, pwidth, pheight, ppos); + return Vector2(ppos[0], ppos[1]); +} + +Ray Camera::get_primary_ray(int x, int y, int xsz, int ysz, int sample) const +{ +#pragma omp single + { + if(!rdir_cache || rdir_cache_width != xsz || rdir_cache_height != ysz) { + printf("calculating primary ray direction cache\n"); + + delete [] rdir_cache; + rdir_cache = new Vector3[xsz * ysz]; + +#pragma omp parallel for + for(int i=0; ix = ppos.x; + rdir->y = ppos.y; + rdir->z = 1.0 / tan(vfov / 2.0); + rdir->normalize(); + + rdir++; + } + } + rdir_cache_width = xsz; + rdir_cache_height = ysz; + } + } + + Ray ray; + ray.origin = pos; + ray.dir = rdir_cache[y * xsz + x]; + + // transform the ray direction with the camera matrix + Matrix4x4 mat = get_matrix(); + mat.m[0][3] = mat.m[1][3] = mat.m[2][3] = mat.m[3][0] = mat.m[3][1] = mat.m[3][2] = 0.0; + mat.m[3][3] = 1.0; + + ray.dir = ray.dir.transformed(mat); + return ray; +} + +TargetCamera::TargetCamera() {} + +TargetCamera::TargetCamera(const Vector3 &pos, const Vector3 &targ) + : Camera(pos), target(targ) +{ +} + +void TargetCamera::set_target(const Vector3 &targ) +{ + target = targ; + cached_matrix_valid = false; // invalidate the cached matrix +} + +const Vector3 &TargetCamera::get_target() const +{ + return target; +} + +void TargetCamera::calc_matrix(Matrix4x4 *mat) const +{ + Vector3 up(0, 1, 0); + Vector3 dir = (target - pos).normalized(); + Vector3 right = cross_product(up, dir); + up = cross_product(dir, right); + + *mat = Matrix4x4( + right.x, up.x, dir.x, pos.x, + right.y, up.y, dir.y, pos.y, + right.z, up.z, dir.z, pos.z, + 0.0, 0.0, 0.0, 1.0); +} + +void FlyCamera::input_move(float x, float y, float z) +{ + static const Vector3 vfwd(0, 0, 1), vright(1, 0, 0); + + Vector3 k = vfwd.transformed(rot); + Vector3 i = vright.transformed(rot); + Vector3 j = cross_product(k, i); + + pos += i * x + j * y + k * z; + cached_matrix_valid = false; +} + +void FlyCamera::input_rotate(float x, float y, float z) +{ + Vector3 axis(x, y, z); + float axis_len = axis.length(); + if(fabs(axis_len) < 1e-5) { + return; + } + rot.rotate(axis / axis_len, -axis_len); + rot.normalize(); + + cached_matrix_valid = false; +} + +void FlyCamera::calc_matrix(Matrix4x4 *mat) const +{ + Matrix4x4 tmat; + tmat.set_translation(pos); + + Matrix3x3 rmat = rot.get_rotation_matrix(); + + *mat = tmat * Matrix4x4(rmat); +} + +/* generates a sample position for sample number sidx, in the unit square + * by recursive subdivision and jittering + */ +static void calc_sample_pos_rec(int sidx, float xsz, float ysz, float *pos) +{ + static const float subpt[4][2] = { + {-0.25, -0.25}, {0.25, -0.25}, {-0.25, 0.25}, {0.25, 0.25} + }; + + if(!sidx) { + return; + } + + /* determine which quadrant to recurse into */ + int quadrant = ((sidx - 1) % 4); + pos[0] += subpt[quadrant][0] * xsz; + pos[1] += subpt[quadrant][1] * ysz; + + calc_sample_pos_rec((sidx - 1) / 4, xsz / 2, ysz / 2, pos); +} diff -r 000000000000 -r 4abdce1361b9 liberebus/src/camera.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liberebus/src/camera.h Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,61 @@ +#ifndef CAMERA_H_ +#define CAMERA_H_ + +#include "vmath/vmath.h" + +class Camera { +protected: + Vector3 pos; + float vfov; // vertical field of view in radians + + mutable Matrix4x4 cached_matrix; + mutable bool cached_matrix_valid; + + mutable Vector3 *rdir_cache; + mutable int rdir_cache_width, rdir_cache_height; + + virtual void calc_matrix(Matrix4x4 *mat) const = 0; + + Vector2 calc_sample_pos(int x, int y, int xsz, int ysz, int sample) const; + +public: + Camera(); + Camera(const Vector3 &pos); + virtual ~Camera(); + + virtual void set_fov(float vfov); + virtual float get_fov() const; + + virtual void set_position(const Vector3 &pos); + virtual const Vector3 &get_position() const; + virtual const Matrix4x4 &get_matrix() const; + + virtual Ray get_primary_ray(int x, int y, int xsz, int ysz, int sample = 0) const; +}; + +class TargetCamera : public Camera { +protected: + Vector3 target; + + void calc_matrix(Matrix4x4 *mat) const; + +public: + TargetCamera(); + TargetCamera(const Vector3 &pos, const Vector3 &targ); + + virtual void set_target(const Vector3 &targ); + virtual const Vector3 &get_target() const; +}; + +class FlyCamera : public Camera { +protected: + Quaternion rot; + + void calc_matrix(Matrix4x4 *mat) const; + +public: + void input_move(float x, float y, float z); + void input_rotate(float x, float y, float z); +}; + +#endif // CAMERA_H_ diff -r 000000000000 -r 4abdce1361b9 liberebus/src/color.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liberebus/src/color.h Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,10 @@ +#ifndef COLOR_H_ +#define COLOR_H_ + +#include "vmath/vector.h" + +typedef Vector3 Color; + +inline float color_luminance(const Color &c) { return c[0] * 0.2126 + c[1] * 0.7152 + c[2] * 0.0722; } + +#endif // COLOR_H_ \ No newline at end of file diff -r 000000000000 -r 4abdce1361b9 liberebus/src/erebus.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liberebus/src/erebus.cc Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,159 @@ +#include +#include +#include +#include +#include "erebus.h" +#include "vmath/vector.h" +#include "image.h" + +using namespace std::chrono; + +struct Rect { + int x, y, width, height; + + bool operator ==(const Rect &r) { return memcmp(this, &r, sizeof r) == 0; } + bool operator !=(const Rect &r) { return memcmp(this, &r, sizeof r) != 0; } +}; + +#define INVALID_RECT Rect{0, 0, 0, 0} + +struct erebus { + Image fbimg; + Vector4 options[ERB_NUM_OPTIONS]; + + // render state + long cur_time; + int cur_pixel_x, cur_pixel_y; + Rect cur_rect; +}; + +static void render_pixel(struct erebus *ctx, int x, int y); + +static std::mt19937 rnd_gen; + +extern "C" { + +struct erebus *erb_init(void) +{ + struct erebus *ctx; + try { + ctx = new struct erebus; + } + catch(...) { + return 0; + } + + ctx->cur_time = 0; + ctx->cur_rect = INVALID_RECT; + return ctx; +} + +void erb_destroy(struct erebus *ctx) +{ + delete ctx; +} + +void erb_setopti(struct erebus *ctx, enum erb_option opt, int val) +{ + ctx->options[opt].x; +} +void erb_setoptf(struct erebus *ctx, enum erb_option opt, float val) +{ + ctx->options[opt].x = val; +} +void erb_setoptfv(struct erebus *ctx, enum erb_option opt, float *vec) +{ + for(int i=0; i<4; i++) { + ctx->options[opt][i] = vec[i]; + } +} + +int erb_getopti(struct erebus *ctx, enum erb_option opt) +{ + return ctx->options[opt].x; +} +float erb_getoptf(struct erebus *ctx, enum erb_option opt) +{ + return ctx->options[opt].x; +} +float *erb_getoptfv(struct erebus *ctx, enum erb_option opt) +{ + return &ctx->options[opt].x; +} + +float *erb_get_framebuffer(struct erebus *ctx) +{ + return ctx->fbimg.get_pixels(); +} + +void erb_begin_frame(struct erebus *ctx, long ms) +{ + ctx->cur_time = ms; +} + +int erb_render(struct erebus *ctx, long timeout) +{ + return erb_render_rect(ctx, 0, 0, ctx->fbimg.get_width(), ctx->fbimg.get_height(), timeout); +} + +int erb_render_rect(struct erebus *ctx, int x, int y, int width, int height, long timeout) +{ + if(!width || !height) return -1; + + Rect rect{x, y, width, height}; + if(ctx->cur_rect != rect) { + ctx->cur_rect = rect; + ctx->cur_pixel_x = x; + ctx->cur_pixel_y = y; + } + + if(timeout > 0) { + auto start_time = monotonic_clock::now(); + while(duration_cast(monotonic_clock::now() - start_time).count() < timeout) { + render_pixel(ctx, ctx->cur_pixel_x, ctx->cur_pixel_y); + + if(++ctx->cur_pixel_x >= ctx->cur_rect.width) { + if(++ctx->cur_pixel_y >= ctx->cur_rect.height) { + ctx->cur_rect = INVALID_RECT; + return 0; + } + } + } + return 1; + } + + for(int i=0; iscene; + //ctx->scene = new Scene; + + return false; // TODO +} + +} // extern "C" + +float randf(float low, float high) +{ + std::uniform_real_distribution unirnd(low, high); + return unirnd(rnd_gen); +} + +static void render_pixel(struct erebus *ctx, int x, int y) +{ + float *pix = ctx->fbimg.get_pixels() + (y * ctx->fbimg.get_width() + x) * 4; + pix[0] = pix[1] = pix[2] = 0.0f; + pix[3] = 1.0f; +} \ No newline at end of file diff -r 000000000000 -r 4abdce1361b9 liberebus/src/erebus.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liberebus/src/erebus.h Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,46 @@ +#ifndef LIBEREBUS_H_ +#define LIBEREBUS_H_ + +struct erebus; + +enum erb_option { + ERB_OPT_WIDTH, + ERB_OPT_HEIGHT, + ERB_OPT_MAX_ITER, + ERB_OPT_NUM_THREADS, + ERB_OPT_GAMMA, + + ERB_NUM_OPTIONS +}; + +#ifdef __cplusplus +extern "C" { +#endif + +struct erebus *erb_init(void); +void erb_destroy(struct erebus *ctx); + +void erb_setopti(struct erebus *ctx, enum erb_option opt, int val); +void erb_setoptf(struct erebus *ctx, enum erb_option opt, float val); +void erb_setoptfv(struct erebus *ctx, enum erb_option opt, float *vec); + +int erb_getopti(struct erebus *ctx, enum erb_option opt); +float erb_getoptf(struct erebus *ctx, enum erb_option opt); +float *erb_getoptfv(struct erebus *ctx, enum erb_option opt); + +float *erb_get_framebuffer(struct erebus *ctx); + +void erb_begin_frame(struct erebus *ctx, long ms); +int erb_render(struct erebus *ctx, long timeout); +int erb_render_rect(struct erebus *ctx, int x, int y, int width, int height, long timeout); + +int erb_get_progress(struct erebus *ctx); + +int erb_load_scene(struct erebus *ctx, const char *fname); + +#ifdef __cplusplus +} +#endif + + +#endif /* LIBEREBUS_H_ */ \ No newline at end of file diff -r 000000000000 -r 4abdce1361b9 liberebus/src/erebus_impl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liberebus/src/erebus_impl.h Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,6 @@ +#ifndef EREBUS_IMPL_H_ +#define EREBUS_IMPL_H_ + +float randf(float low = 0.0f, float high = 1.0f); + +#endif // EREBUS_IMPL_H_ \ No newline at end of file diff -r 000000000000 -r 4abdce1361b9 liberebus/src/geomobj.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liberebus/src/geomobj.h Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,50 @@ +#ifndef GEOMOBJ_H_ +#define GEOMOBJ_H_ + +#include "object.h" +#include "brdf.h" + +class GeomObject : public Object { +public: + Reflectance *brdf; + + ObjType get_type() const override; + + bool intersect(const Ray &ray, RayHit *hit = 0) const override; +}; + +class Sphere : public GeomObject { +public: + bool intersect(const Ray &ray, RayHit *hit = 0) const override; +}; + +class Box : public GeomObject { +public: + bool intersect(const Ray &ray, RayHit *hit = 0) const override; +}; + +class Triangle : public GeomObject { +public: + Vector3 v[3]; + Vector3 normal; + Vector3 vnorm[3]; + Vector2 vtex[3]; + + bool intersect(const Ray &ray, RayHit *hit = 0) const override; +}; + +class Mesh : public GeomObject { +private: + std::vector faces; + +public: + void begin(); + void vertex(float x, float y, float z); + void normal(float x, float y, float z); + void texcoord(float u, float v); + void end(); + + bool intersect(const Ray &ray, RayHit *hit = 0) const override; +}; + +#endif // GEOMOBJ_H_ \ No newline at end of file diff -r 000000000000 -r 4abdce1361b9 liberebus/src/image.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liberebus/src/image.h Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,35 @@ +#ifndef IMAGE_H_ +#define IMAGE_H_ + +template +class Image { +private: + int width, height; + T *pixels; + bool own_pixels; + +public: + Image(); + ~Image(); + + Image(const Image &img); + Image &operator =(const Image &img); + + Image(const Image &&img); + Image &&operator =(const Image &&img); + + void create(int xsz, int ysz, const T *pix = 0); + void destroy(); + + int get_width() const; + int get_height() const; + + void set_pixels(int xsz, int ysz, T *pix); + T *get_pixels() const; + + bool load(const char *fname); +}; + +#include "image.inl" + +#endif // IMAGE_H_ diff -r 000000000000 -r 4abdce1361b9 liberebus/src/image.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liberebus/src/image.inl Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,143 @@ +#include +#include "imago2.h" +#include "image.h" + +template +Image::Image() +{ + pixels = 0; + own_pixels = true; + width = height = 0; +} + +template +Image::~Image() +{ + destroy(); +} + +template +Image::Image(const Image &img) +{ + pixels = 0; + own_pixels = false; + + create(img.width, img.height, img.pixels); +} + +template +Image &Image::operator =(const Image &img) +{ + if(this != &img) { + destroy(); + create(img.width, img.height, img.pixels); + } + return *this; +} + +template +Image::Image(const Image &&img) +{ + width = img.width; + height = img.height; + pixels = img.pixels; + own_pixels = img.own_pixels; + + img.pixels = 0; + img.width = img.height = 0; +} + +template +Image &&Image::operator =(const Image &&img) +{ + if(this != &img) { + width = img.width; + height = img.height; + pixels = img.pixels; + own_pixels = img.own_pixels; + + img.pixels = 0; + img.width = img.height = 0; + } + return *this; +} + +template +void Image::create(int xsz, int ysz, const T *pixels) +{ + destroy(); + + this->pixels = new T[xsz * ysz * 4]; + if(pixels) { + memcpy(this->pixels, pixels, xsz * ysz * 4 * sizeof(T)); + } else { + memset(this->pixels, 0, xsz * ysz * 4 * sizeof(T)); + } + width = xsz; + height = ysz; + own_pixels = true; +} + +template +void Image::destroy() +{ + if(own_pixels) { + delete [] pixels; + } + pixels = 0; + width = height = 0; + own_pixels = true; +} + +template +int Image::get_width() const +{ + return width; +} + +template +int Image::get_height() const +{ + return height; +} + +template +void Image::set_pixels(int xsz, int ysz, T *pixels) +{ + destroy(); + + this->pixels = pixels; + width = xsz; + height = ysz; + own_pixels = false; +} + +template +T *Image::get_pixels() const +{ + return pixels; +} + +bool Image::load(const char *fname) +{ + int xsz, ysz; + unsigned char *pix = (unsigned char*)img_load_pixels(fname, &xsz, &ysz, IMG_FMT_RGBA32); + if(!pix) { + return false; + } + + create(xsz, ysz, pix); + return true; +} + +bool Image::load(const char *fname) +{ + int xsz, ysz; + float *pix = (float*)img_load_pixels(fname, &xsz, &ysz, IMG_FMT_RGBAF); + if(!pix) { + return false; + } + + create(xsz, ysz, pix); + return true; +} \ No newline at end of file diff -r 000000000000 -r 4abdce1361b9 liberebus/src/object.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liberebus/src/object.cc Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,60 @@ +#include "object.h" + +Object::Object() +{ + name = ""; + inv_xform_valid = false; +} + +ObjType Object::get_type() const +{ + return ObjType::null; +} + +void Object::set_name(const char *name) +{ + this->name = name; +} + +const char *Object::get_name() const +{ + return name.c_str(); +} + +void Object::set_xform(const Matrix4x4 &mat) +{ + xform = mat; + inv_xform_valid = false; +} + +void Object::set_xform(const Matrix4x4 &mat, const Matrix4x4 &inv_mat) +{ + xform = mat; + inv_xform = inv_mat; + inv_xform_valid = true; +} + +Matrix4x4 &Object::get_xform() +{ + inv_xform_valid = false; + return xform; +} + +const Matrix4x4 &Object::get_xform() const +{ + return xform; +} + +const Matrix4x4 &Object::get_inv_xform() const +{ + if(!inv_xform_valid) { + inv_xform = xform.inverse(); + inv_xform_valid = true; + } + return inv_xform; +} + +bool Object::intersect(const Ray &ray, RayHit *hit) const +{ + return false; +} \ No newline at end of file diff -r 000000000000 -r 4abdce1361b9 liberebus/src/object.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liberebus/src/object.h Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,44 @@ +#ifndef OBJECT_H_ +#define OBJECT_H_ + +#include +#include "vmath/ray.h" + +class Object; + +struct RayHit { + float dist; + const Ray world_ray, local_ray; + + const Object *obj, *subobj; +}; + +enum class ObjType { null, geom, camera }; + +class Object { +private: + std::string name; + Matrix4x4 xform; + mutable Matrix4x4 inv_xform; + mutable bool inv_xform_valid; + +public: + Object(); + virtual ~Object() = default; + + virtual ObjType get_type() const; + + virtual void set_name(const char *name); + virtual const char *get_name() const; + + virtual void set_xform(const Matrix4x4 &mat); + virtual void set_xform(const Matrix4x4 &mat, const Matrix4x4 &inv_mat); + + virtual Matrix4x4 &get_xform(); // invalidates inv_xform + virtual const Matrix4x4 &get_xform() const; + virtual const Matrix4x4 &get_inv_xform() const; + + virtual bool intersect(const Ray &ray, RayHit *hit = 0) const; +}; + +#endif // OBJECT_H_ \ No newline at end of file diff -r 000000000000 -r 4abdce1361b9 liberebus/src/scene.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liberebus/src/scene.h Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,23 @@ +#ifndef SCENE_H_ +#define SCENE_H_ + +#include +#include "snode.h" +#include "camera.h" + +class Scene { +private: + std::vector objects; + std::vector nodes; + + Camera *active_cam; + +public: + Scene(); + ~Scene(); + + void add_object(Object *obj); + Object *get_object(int idx); +}; + +#endif // SCENE_H_ \ No newline at end of file diff -r 000000000000 -r 4abdce1361b9 liberebus/src/snode.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liberebus/src/snode.h Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,41 @@ +#ifndef SNODE_H_ +#define SNODE_H_ + +#include +#include "object.h" +#include "vmath/vmath.h" + +class SceneNode { +private: + Vector3 pos; + Quaternion rot; + Vector3 scale; + + std::vector obj; + + SceneNode *parent; + std::vector children; + +public: + void add_child(SceneNode *node); + + int get_num_children() const; + SceneNode *get_child(int idx) const; + + void set_position(const Vector3 &pos); + void set_rotation(const Quaternion &rot); + void set_scaling(const Vector3 &scale); + + const Vector3 &get_node_position() const; + const Quaternion &get_node_rotation() const; + const Vector3 &get_node_scaling() const; + + const Vector3 &get_position() const; + const Quaternion &get_rotation() const; + const Vector3 &get_scaling() const; + + void update_node(long msec = 0) const; + void update(long msec = 0) const; +}; + +#endif // SNODE_H_ \ No newline at end of file diff -r 000000000000 -r 4abdce1361b9 liberebus/src/texture.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liberebus/src/texture.h Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,30 @@ +#ifndef TEXTURE_H_ +#define TEXTURE_H_ + +#include "image.h" +#include "color.h" + +class Texture { +public: + Image img; + + inline Color lookup(float u, float v) const; + + bool load(const char *fname) { return img.load(fname); } +}; + + +inline Color Texture::lookup(float u, float v) const +{ + int xsz = img.get_width(); + int ysz = img.get_height(); + + int x = (float)u / (float)xsz; + int y = (float)v / (float)ysz; + + float *pix = img.get_pixels() + ((y % ysz) * xsz + (x % xsz)) * 4; + return Color(pix[0], pix[1], pix[2]); +} + + +#endif // TEXTURE_H_ \ No newline at end of file diff -r 000000000000 -r 4abdce1361b9 src/main.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main.cc Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,141 @@ +#include +#include +#include +#include "opengl.h" + +static bool init(); +static void cleanup(); +static void resize_rtarget(int xsz, int ysz); +static void update_rect(int x, int y, int xsz, int ysz, float *pixels); +static void display(); +static void reshape(int x, int y); +static void keyb(unsigned char key, int x, int y); +static void mouse(int bn, int st, int x, int y); +static int next_pow2(int x); + +static int width, height, rtex_width, rtex_height; +static unsigned int rtex; + +int main(int argc, char **argv) +{ + glutInitWindowSize(1024, 600); + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); + glutCreateWindow("erebus OpenGL frontend"); + + glutDisplayFunc(display); + glutReshapeFunc(reshape); + glutKeyboardFunc(keyb); + glutMouseFunc(mouse); + + if(!init()) { + return 1; + } + atexit(cleanup); + + glutMainLoop(); +} + +static bool init() +{ + return true; +} + +static void cleanup() +{ +} + +static void resize_rtarget(int xsz, int ysz) +{ + static unsigned char *defpix; + + width = xsz; + height = ysz; + + if(xsz <= rtex_width && ysz <= rtex_height) { + return; + } + rtex_width = next_pow2(xsz); + rtex_height = next_pow2(ysz); + + printf("resizing framebuffer texture: %dx%d\n", rtex_width, rtex_height); + + if(!rtex) { + glGenTextures(1, &rtex); + } + + delete [] defpix; + defpix = new unsigned char[rtex_width * rtex_height * 4]; + unsigned char *ptr = defpix; + for(int i=0; i> 4) & 1) == ((j >> 4) & 1); + + int val = chess ? 64 : 48; + + *ptr++ = val; + *ptr++ = val; + *ptr++ = val; + *ptr++ = 255; + } + } + + glBindTexture(GL_TEXTURE_2D, rtex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, rtex_width, rtex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, defpix); +} + +static void update_rect(int x, int y, int xsz, int ysz, float *pixels) +{ + glBindTexture(GL_TEXTURE_2D, rtex); + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, xsz, ysz, GL_RGBA, GL_FLOAT, pixels); +} + +static void display() +{ + glBindTexture(GL_TEXTURE_2D, rtex); + glEnable(GL_TEXTURE_2D); + + float maxu = (float)width / (float)rtex_width; + float maxv = (float)height / (float)rtex_height; + + glBegin(GL_QUADS); + glTexCoord2f(0, maxv); glVertex2f(-1, -1); + glTexCoord2f(maxu, maxv); glVertex2f(1, -1); + glTexCoord2f(maxu, 0); glVertex2f(1, 1); + glTexCoord2f(0, 0); glVertex2f(-1, 1); + glEnd(); + + glDisable(GL_TEXTURE_2D); + + glutSwapBuffers(); + assert(glGetError() == GL_NO_ERROR); +} + +static void reshape(int x, int y) +{ + glViewport(0, 0, x, y); + resize_rtarget(x, y); +} + +static void keyb(unsigned char key, int x, int y) +{ + switch(key) { + case 27: + exit(0); + } +} + +static void mouse(int bn, int st, int x, int y) +{ +} + +static int next_pow2(int x) +{ + int res = 2; + while(res < x) { + res <<= 1; + } + return res; +} \ No newline at end of file diff -r 000000000000 -r 4abdce1361b9 src/opengl.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/opengl.cc Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,63 @@ +#include "opengl.h" +#include + + + +void load_matrix(const Matrix4x4 &m) +{ +#ifdef SINGLE_PRECISION_MATH + if(glLoadTransposeMatrixfARB) { + glLoadTransposeMatrixfARB((float*)&m); + } else { + Matrix4x4 tmat = m.transposed(); + glLoadMatrixf((float*)&tmat); + } +#else + if(glLoadTransposeMatrixdARB) { + glLoadTransposeMatrixdARB((double*)&m); + } else { + Matrix4x4 tmat = m.transposed(); + glLoadMatrixd((double*)&tmat); + } +#endif +} + +void mult_matrix(const Matrix4x4 &m) +{ +#ifdef SINGLE_PRECISION_MATH + if(glMultTransposeMatrixfARB) { + glMultTransposeMatrixfARB((float*)&m); + } else { + Matrix4x4 tmat = m.transposed(); + glMultMatrixf((float*)&tmat); + } +#else + if(glMultTransposeMatrixdARB) { + glMultTransposeMatrixdARB((double*)&m); + } else { + Matrix4x4 tmat = m.transposed(); + glMultMatrixd((double*)&tmat); + } +#endif +} + +const char *strglerr(int err) +{ + static const char *errnames[] = { + "GL_INVALID_ENUM", + "GL_INVALID_VALUE", + "GL_INVALID_OPERATION", + "GL_STACK_OVERFLOW", + "GL_STACK_UNDERFLOW", + "GL_OUT_OF_MEMORY", + "GL_INVALID_FRAMEBUFFER_OPERATION" + }; + + if(!err) { + return "GL_NO_ERROR"; + } + if(err < GL_INVALID_ENUM || err > GL_OUT_OF_MEMORY) { + return ""; + } + return errnames[err - GL_INVALID_ENUM]; +} diff -r 000000000000 -r 4abdce1361b9 src/opengl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/opengl.h Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,29 @@ +#ifndef OPENGL_H_ +#define OPENGL_H_ + +#include + +#ifndef __APPLE__ +#include +#else +#include +#endif + +#define CHECKGLERR \ + do { \ + int err = glGetError(); \ + if(err) { \ + fprintf(stderr, "%s:%d: OpenGL error 0x%x: %s\n", __FILE__, __LINE__, err, strglerr(err)); \ + abort(); \ + } \ + } while(0) + + +class Matrix4x4; + +void load_matrix(const Matrix4x4 &m); +void mult_matrix(const Matrix4x4 &m); + +const char *strglerr(int err); + +#endif /* OPENGL_H_ */ diff -r 000000000000 -r 4abdce1361b9 src/sdr.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdr.c Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,427 @@ +/* +Printblobs - halftoning display hack +Copyright (C) 2013 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#include +#include +#include +#include +#include +#include +#include + +#if defined(unix) || defined(__unix__) +#include +#include +#endif /* unix */ + +#include "sdr.h" + +static const char *sdrtypestr(unsigned int sdrtype); + +unsigned int create_vertex_shader(const char *src) +{ + return create_shader(src, GL_VERTEX_SHADER); +} + +unsigned int create_pixel_shader(const char *src) +{ + return create_shader(src, GL_FRAGMENT_SHADER); +} + +unsigned int create_tessctl_shader(const char *src) +{ + return create_shader(src, GL_TESS_CONTROL_SHADER); +} + +unsigned int create_tesseval_shader(const char *src) +{ + return create_shader(src, GL_TESS_EVALUATION_SHADER); +} + +unsigned int create_geometry_shader(const char *src) +{ + return create_shader(src, GL_GEOMETRY_SHADER); +} + +unsigned int create_shader(const char *src, unsigned int sdr_type) +{ + unsigned int sdr; + int success, info_len; + char *info_str = 0; + GLenum err; + + sdr = glCreateShader(sdr_type); + assert(glGetError() == GL_NO_ERROR); + glShaderSource(sdr, 1, &src, 0); + err = glGetError(); + assert(err == GL_NO_ERROR); + glCompileShader(sdr); + assert(glGetError() == GL_NO_ERROR); + + glGetShaderiv(sdr, GL_COMPILE_STATUS, &success); + assert(glGetError() == GL_NO_ERROR); + glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len); + assert(glGetError() == GL_NO_ERROR); + + if(info_len) { + if((info_str = malloc(info_len + 1))) { + glGetShaderInfoLog(sdr, info_len, 0, info_str); + assert(glGetError() == GL_NO_ERROR); + } + } + + if(success) { + fprintf(stderr, info_str ? "done: %s\n" : "done\n", info_str); + } else { + fprintf(stderr, info_str ? "failed: %s\n" : "failed\n", info_str); + glDeleteShader(sdr); + sdr = 0; + } + + free(info_str); + return sdr; +} + +void free_shader(unsigned int sdr) +{ + glDeleteShader(sdr); +} + +unsigned int load_vertex_shader(const char *fname) +{ + return load_shader(fname, GL_VERTEX_SHADER); +} + +unsigned int load_pixel_shader(const char *fname) +{ + return load_shader(fname, GL_FRAGMENT_SHADER); +} + +unsigned int load_tessctl_shader(const char *fname) +{ + return load_shader(fname, GL_TESS_CONTROL_SHADER); +} + +unsigned int load_tesseval_shader(const char *fname) +{ + return load_shader(fname, GL_TESS_EVALUATION_SHADER); +} + +unsigned int load_geometry_shader(const char *fname) +{ + return load_shader(fname, GL_GEOMETRY_SHADER); +} + +unsigned int load_shader(const char *fname, unsigned int sdr_type) +{ +#if defined(unix) || defined(__unix__) + struct stat st; +#endif + unsigned int sdr; + size_t filesize; + FILE *fp; + char *src; + + if(!(fp = fopen(fname, "r"))) { + fprintf(stderr, "failed to open shader %s: %s\n", fname, strerror(errno)); + return 0; + } + +#if defined(unix) || defined(__unix__) + fstat(fileno(fp), &st); + filesize = st.st_size; +#else + fseek(fp, 0, SEEK_END); + filesize = ftell(fp); + fseek(fp, 0, SEEK_SET); +#endif /* unix */ + + if(!(src = malloc(filesize + 1))) { + fclose(fp); + return 0; + } + fread(src, 1, filesize, fp); + src[filesize] = 0; + fclose(fp); + + fprintf(stderr, "compiling %s shader: %s... ", sdrtypestr(sdr_type), fname); + sdr = create_shader(src, sdr_type); + + free(src); + return sdr; +} + + +unsigned int get_vertex_shader(const char *fname) +{ + return get_shader(fname, GL_VERTEX_SHADER); +} + +unsigned int get_pixel_shader(const char *fname) +{ + return get_shader(fname, GL_FRAGMENT_SHADER); +} + +unsigned int get_tessctl_shader(const char *fname) +{ + return get_shader(fname, GL_TESS_CONTROL_SHADER); +} + +unsigned int get_tesseval_shader(const char *fname) +{ + return get_shader(fname, GL_TESS_EVALUATION_SHADER); +} + +unsigned int get_geometry_shader(const char *fname) +{ + return get_shader(fname, GL_GEOMETRY_SHADER); +} + +unsigned int get_shader(const char *fname, unsigned int sdr_type) +{ + unsigned int sdr; + if(!(sdr = load_shader(fname, sdr_type))) { + return 0; + } + return sdr; +} + + +/* ---- gpu programs ---- */ + +unsigned int create_program(void) +{ + unsigned int prog = glCreateProgram(); + assert(glGetError() == GL_NO_ERROR); + return prog; +} + +unsigned int create_program_link(unsigned int sdr0, ...) +{ + unsigned int prog, sdr; + va_list ap; + + if(!(prog = create_program())) { + return 0; + } + + attach_shader(prog, sdr0); + if(glGetError()) { + return 0; + } + + va_start(ap, sdr0); + while((sdr = va_arg(ap, unsigned int))) { + attach_shader(prog, sdr); + if(glGetError()) { + return 0; + } + } + va_end(ap); + + if(link_program(prog) == -1) { + free_program(prog); + return 0; + } + return prog; +} + +unsigned int create_program_load(const char *vfile, const char *pfile) +{ + unsigned int vs = 0, ps = 0; + + if(vfile && *vfile && !(vs = get_vertex_shader(vfile))) { + return 0; + } + if(pfile && *pfile && !(ps = get_pixel_shader(pfile))) { + return 0; + } + return create_program_link(vs, ps, 0); +} + +void free_program(unsigned int sdr) +{ + glDeleteProgram(sdr); +} + +void attach_shader(unsigned int prog, unsigned int sdr) +{ + glAttachShader(prog, sdr); + assert(glGetError() == GL_NO_ERROR); +} + +int link_program(unsigned int prog) +{ + int linked, info_len, retval = 0; + char *info_str = 0; + + glLinkProgram(prog); + assert(glGetError() == GL_NO_ERROR); + glGetProgramiv(prog, GL_LINK_STATUS, &linked); + assert(glGetError() == GL_NO_ERROR); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len); + assert(glGetError() == GL_NO_ERROR); + + if(info_len) { + if((info_str = malloc(info_len + 1))) { + glGetProgramInfoLog(prog, info_len, 0, info_str); + assert(glGetError() == GL_NO_ERROR); + } + } + + if(linked) { + fprintf(stderr, info_str ? "linking done: %s\n" : "linking done\n", info_str); + } else { + fprintf(stderr, info_str ? "linking failed: %s\n" : "linking failed\n", info_str); + retval = -1; + } + + free(info_str); + return retval; +} + +int bind_program(unsigned int prog) +{ + GLenum err; + + glUseProgram(prog); + if(prog && (err = glGetError()) != GL_NO_ERROR) { + /* maybe the program is not linked, try linking first */ + if(err == GL_INVALID_OPERATION) { + if(link_program(prog) == -1) { + return -1; + } + glUseProgram(prog); + return glGetError() == GL_NO_ERROR ? 0 : -1; + } + return -1; + } + return 0; +} + +/* ugly but I'm not going to write the same bloody code over and over */ +#define BEGIN_UNIFORM_CODE \ + int loc, curr_prog; \ + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); \ + if((unsigned int)curr_prog != prog && bind_program(prog) == -1) { \ + return -1; \ + } \ + if((loc = glGetUniformLocation(prog, name)) != -1) + +#define END_UNIFORM_CODE \ + if((unsigned int)curr_prog != prog) { \ + bind_program(curr_prog); \ + } \ + return loc == -1 ? -1 : 0 + +int set_uniform_int(unsigned int prog, const char *name, int val) +{ + BEGIN_UNIFORM_CODE { + glUniform1i(loc, val); + } + END_UNIFORM_CODE; +} + +int set_uniform_float(unsigned int prog, const char *name, float val) +{ + BEGIN_UNIFORM_CODE { + glUniform1f(loc, val); + } + END_UNIFORM_CODE; +} + +int set_uniform_float2(unsigned int prog, const char *name, float x, float y) +{ + BEGIN_UNIFORM_CODE { + glUniform2f(loc, x, y); + } + END_UNIFORM_CODE; +} + +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z) +{ + BEGIN_UNIFORM_CODE { + glUniform3f(loc, x, y, z); + } + END_UNIFORM_CODE; +} + +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w) +{ + BEGIN_UNIFORM_CODE { + glUniform4f(loc, x, y, z, w); + } + END_UNIFORM_CODE; +} + +int set_uniform_matrix4(unsigned int prog, const char *name, float *mat) +{ + BEGIN_UNIFORM_CODE { + glUniformMatrix4fv(loc, 1, GL_FALSE, mat); + } + END_UNIFORM_CODE; +} + +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat) +{ + BEGIN_UNIFORM_CODE { + glUniformMatrix4fv(loc, 1, GL_TRUE, mat); + } + END_UNIFORM_CODE; +} + +int get_attrib_loc(unsigned int prog, const char *name) +{ + int loc, curr_prog; + + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); + if((unsigned int)curr_prog != prog && bind_program(prog) == -1) { + return -1; + } + + loc = glGetAttribLocation(prog, (char*)name); + + if((unsigned int)curr_prog != prog) { + bind_program(curr_prog); + } + return loc; +} + +void set_attrib_float3(int attr_loc, float x, float y, float z) +{ + glVertexAttrib3f(attr_loc, x, y, z); +} + +static const char *sdrtypestr(unsigned int sdrtype) +{ + switch(sdrtype) { + case GL_VERTEX_SHADER: + return "vertex"; + case GL_FRAGMENT_SHADER: + return "pixel"; + case GL_TESS_CONTROL_SHADER: + return "tessellation control"; + case GL_TESS_EVALUATION_SHADER: + return "tessellation evaluation"; + case GL_GEOMETRY_SHADER: + return "geometry"; + + default: + break; + } + return ""; +} diff -r 000000000000 -r 4abdce1361b9 src/sdr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdr.h Sun Apr 27 16:02:47 2014 +0300 @@ -0,0 +1,76 @@ +/* +Printblobs - halftoning display hack +Copyright (C) 2013 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#ifndef SDR_H_ +#define SDR_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* ---- shaders ---- */ +unsigned int create_vertex_shader(const char *src); +unsigned int create_pixel_shader(const char *src); +unsigned int create_tessctl_shader(const char *src); +unsigned int create_tesseval_shader(const char *src); +unsigned int create_geometry_shader(const char *src); +unsigned int create_shader(const char *src, unsigned int sdr_type); +void free_shader(unsigned int sdr); + +unsigned int load_vertex_shader(const char *fname); +unsigned int load_pixel_shader(const char *fname); +unsigned int load_tessctl_shader(const char *fname); +unsigned int load_tesseval_shader(const char *fname); +unsigned int load_geometry_shader(const char *fname); +unsigned int load_shader(const char *src, unsigned int sdr_type); + +unsigned int get_vertex_shader(const char *fname); +unsigned int get_pixel_shader(const char *fname); +unsigned int get_tessctl_shader(const char *fname); +unsigned int get_tesseval_shader(const char *fname); +unsigned int get_geometry_shader(const char *fname); +unsigned int get_shader(const char *fname, unsigned int sdr_type); + +int add_shader(const char *fname, unsigned int sdr); +int remove_shader(const char *fname); + +/* ---- gpu programs ---- */ +unsigned int create_program(void); +unsigned int create_program_link(unsigned int sdr0, ...); +unsigned int create_program_load(const char *vfile, const char *pfile); +void free_program(unsigned int sdr); + +void attach_shader(unsigned int prog, unsigned int sdr); +int link_program(unsigned int prog); +int bind_program(unsigned int prog); + +int set_uniform_int(unsigned int prog, const char *name, int val); +int set_uniform_float(unsigned int prog, const char *name, float val); +int set_uniform_float2(unsigned int prog, const char *name, float x, float y); +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z); +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w); +int set_uniform_matrix4(unsigned int prog, const char *name, float *mat); +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat); + +int get_attrib_loc(unsigned int prog, const char *name); +void set_attrib_float3(int attr_loc, float x, float y, float z); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SDR_H_ */