diff --git a/rtrt/cmdflags.h b/rtrt/cmdflags.h new file mode 100644 index 0000000..215a4d2 --- /dev/null +++ b/rtrt/cmdflags.h @@ -0,0 +1,17 @@ +#ifndef CMDFLAGS_H +#define CMDFLAGS_H + + +// include google flags +#include +#include + +DECLARE_bool(fullscreen); +DECLARE_bool(fps); +DECLARE_int32(width); +DECLARE_int32(height); +DECLARE_int32(interval); + +void parse_commandline(int *argc, char ***argv); + +#endif // CMDFLAGS_H diff --git a/rtrt/modules/cmdflags.cpp b/rtrt/modules/cmdflags.cpp new file mode 100644 index 0000000..be85a45 --- /dev/null +++ b/rtrt/modules/cmdflags.cpp @@ -0,0 +1,40 @@ + +/** + @file modules/cmdflags.cpp + + Contains the command line flags and procesing functions. + + */ + + + + +#include + +// command line options +DEFINE_int32( width, 640, "Set the screen width" ); +DEFINE_int32( height, 480, "Set the screen height" ); +DEFINE_bool( fullscreen, false, "Set the screen to fullscreen" ); +DEFINE_bool( fps, true, "Show the frame rate in window mode" ); +DEFINE_int32( interval, 0, "Screen refresh interval" ); + +/** + parse_commandline parses the main functions command line options + and sets up the logger + + @param argc number of command line arguments to parse + @param argv list of command line arguments + */ +void parse_commandline(int *argc, char ***argv) +{ + /// parse command line params + google::SetUsageMessage( "rtrt [options]" ); + FLAGS_logtostderr = true; + google::ParseCommandLineFlags(argc, argv, true); + + /// setup logger + google::InitGoogleLogging( *argv[0] ); + /// setup term handler + google::InstallFailureSignalHandler(); +} + diff --git a/rtrt/modules/image.cpp b/rtrt/modules/image.cpp new file mode 100644 index 0000000..32a161d --- /dev/null +++ b/rtrt/modules/image.cpp @@ -0,0 +1,89 @@ +#include "image.h" + +Image::Image() + : _width(0), _height(0), _data(NULL), ready(false) +{ +} + +Image::Image(size_t w, size_t h) + : _width(0), _height(0), _data(NULL), ready(false) +{ + create_image(w, h); +} + +Image::~Image() +{ + destroy_image(); +} + + +void Image::create_image(size_t w, size_t h) +{ + destroy_image(); + _width = w; + _height = h; + LOG(INFO) << "Creating new image: " << w << "x" << h; + _data = new iColor[_width * _height]; + ready = _data != NULL; + fill_with_color(0); +} + +void Image::destroy_image() +{ + if(ready || _data != NULL) + { + delete[] _data; + } + ready = false; + _data = NULL; +} + +void Image::fill_with_color(boost::uint8_t r, boost::uint8_t g, boost::uint8_t b) +{ + if(!ready) return; + for(size_t y = 0; y < _height; ++y) + { + for(size_t x = 0; x < _width; ++x) + { + _data[at(x,y)].r = r; + _data[at(x,y)].g = g; + _data[at(x,y)].b = b; + _data[at(x,y)].a = 0; + } + } +} + +void Image::fill_with_color(boost::uint32_t c) +{ + if(!ready) return; + for(size_t y = 0; y < _height; ++y) + { + for(size_t x = 0; x < _width; ++x) + { + _data[at(x,y)].color = c; + } + } +} + + +void Image::fill_with_random() +{ + if(!ready) return; + for(size_t y = 0; y < _height; ++y) + { + for(size_t x = 0; x < _width; ++x) + { + _data[at(x,y)].color = rand(); + } + } +} + +void Image::set(size_t x, size_t y, color c) +{ + if(!ready) return; + clamp(c); + _data[at(x,y)].r = c.x*255; + _data[at(x,y)].g = c.y*255; + _data[at(x,y)].b = c.z*255; + _data[at(x,y)].a = 0; +} diff --git a/rtrt/modules/image.h b/rtrt/modules/image.h new file mode 100644 index 0000000..4d2082e --- /dev/null +++ b/rtrt/modules/image.h @@ -0,0 +1,48 @@ +#ifndef IMAGE_H +#define IMAGE_H + +// C++ includes +#include +#include + +// Project includes +#include +#include +#include + +union iColor +{ + boost::uint32_t color; + struct { + boost::uint8_t r, g, b, a; + }; +}; + +class Image +{ +public: + Image(); + Image(size_t, size_t); + ~Image(); + + void create_image(size_t, size_t); + void destroy_image(); + + void fill_with_color(boost::uint8_t, boost::uint8_t, boost::uint8_t); + void fill_with_color(boost::uint32_t); + void fill_with_random(); + + + inline boost::uint32_t width() { return(_width); } + inline boost::uint32_t height() { return(_height); } + inline iColor *data() { return(_data); } + inline size_t at(size_t x, size_t y) { return((y * _width) + x); } + + void set(size_t , size_t, color); +private: + boost::uint32_t _width, _height; + iColor *_data; + bool ready; +}; + +#endif // IMAGE_H diff --git a/rtrt/modules/vec4.h b/rtrt/modules/vec4.h new file mode 100644 index 0000000..80b04ff --- /dev/null +++ b/rtrt/modules/vec4.h @@ -0,0 +1,127 @@ +/** + * \file vec4.h + * \brief Defines the base vector type + * + * Defines the single-precision 128 bit vector struct. This structure + * is used to hold 4 floats, and is used to take advantage of SSE instructions. + * Support functions are defined in vec_func.h + * + * \author Byron Heads + * \date July 14, 2011 + */ + +#ifndef VECT4_H +#define VECT4_H + +/** + * \struct vec4 + * \brief Ray-tracers four float vector. + * + * Used in vec_func, and other parts if the ray-tracer. + * Only has constructors, operators defined in vec_func.h + * + */ +struct vec4 +{ + float x, ///< x componant of vector. + y, ///< y componant of vector. + z, ///< z componant of vector. + w; ///< w componant of vector, normally this should be zero. + + /** + * \brief Default constructor + * + * Default constructor, all values are zero + */ + vec4() + : x(0), y(0), z(0), w(0) {} + + /** + * \brief Destructor + * + * Destructor, does nothing here. + */ + ~vec4() {} + + /** + * \brief Four float constructor + * + * Constructor taking 4 flosting point numbers. Defaults to 0. + */ + vec4( float _x, float _y=0, float _z=0, float _w=0 ) + : x(_x), y(_y), z(_z), w(_w) {} + + /** + * \brief Array constructor + * + * Constructor taking an array of 4 floats. + */ + vec4( float f[4] ) + : x(f[0]), y(f[1]), z(f[2]), w(f[3]) {} + + /** + * \brief Scalar constructor. + * + * Constructor taking a float, all elements except get set. If w2 + * is true then w gets set as well, else it is set to zero. + * + * \param f Values to set x, y, z, and w if w2 is true. + * \param w2 If true w is set to the value of f. + */ + vec4( float f, bool w2 = false ) + : x(f), y(f), z(f), w( w2 ? f: 0 ) {} + + /** + * \brief Copy Constructor + * + * Constructor that copies the value of v. + * + * \param v Vector refrence to copy from. + */ + vec4( const vec4 &v ) + : x(v.x), y(v.y), z(v.z), w(v.w) {} + + + /** + * \brief Assignment operator. + * + * Assignment operator. Copies another vec4 object. + * + * \param o Object to copy; + * \return Refrence to self, is a copy of o + */ + vec4 &operator=( const vec4 &o ) + { + if( this != &o ) + { + x = o.x; + y = o.y; + z = o.z; + w = o.w; + } + return *this; + } + + /** + * \brief Scalar assignment operator. + * + * Scalar assignment operator. Copies a scalar value. W is copied. + * + * \param v Scalar value to set vector to. + * \return Refrence to self, is set to v. + */ + vec4 &operator=( const float v ) + { + x = y = z = w = v; + return *this; + } + +}__attribute__((aligned(16))); ///< Make sure this is 16 byte aligned. Can use movaps + +/** + * \typedef vec4 color + * rtrt Colors are also vectors +*/ +typedef vec4 color; + +#endif diff --git a/rtrt/modules/vec_func.cpp b/rtrt/modules/vec_func.cpp new file mode 100644 index 0000000..0129181 --- /dev/null +++ b/rtrt/modules/vec_func.cpp @@ -0,0 +1,681 @@ +/** + * \file vec_func.cpp + * \brief This file contain several vector math functions. + * + * This files contains all of the vector functions. These functions + * are used to compute the core elements of the ray-tracer. Hence these + * functions need to be fast. Most functions are written in assembly using + * SSE. + * + * The vector type is defined in vec4.h. Vectors will also be used to + * hold color information. Thus this file contains color functions as well. + * + * \author Byron Heads + * \date July 14, 2011 + * + * \todo Add cross product + * \todo Add Triple product + * \todo Add vector operations + * \todo Add color operations +*/ + +#include + + + +/** + * \brief Adds two vec4s. + * + * The method adds two vec4 objects togeather. Uses SSE. + * + * \param lhs Left hand side of operation. + * \param rhs Right hand side of operation. + * \return Returns a constant vec4 object that is the results of lhs + rhs. + */ +const vec4 operator+( const vec4 &lhs, const vec4 &rhs ) +{ + vec4 ret; + asm( "movaps %1, %%xmm0 \n\t" + "movaps %2, %%xmm1 \n\t" + "addps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(ret) + : "m"(lhs), "m"(rhs) + : "xmm0", "xmm1" + ); + return( ret ); +} + + +/** + * \brief Adds Scalar to a vec4. + * + * The method adds a Scalar to a vec4. Uses SSE. + * + * \param lhs Left hand side of operation. + * \param rhs Right hand side of operation. + * \return Returns a constant vec4 object that is the results of lhs + rhs. + */ +const vec4 operator+( const vec4 &lhs, float rhs ) +{ + vec4 ret; + asm( "movaps %1, %%xmm0 \n\t" + "movss %2, %%xmm1 \n\t" + "shufps $0x00, %%xmm1, %%xmm1 \n\t" + "addps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(ret) + : "m"(lhs), "m"(rhs) + : "xmm0", "xmm1" + ); + return( ret ); +} + +/** + * \brief Adds Scalar to a vec4. + * + * The method adds a Scalar to a vec4. Uses SSE. + * + * \param lhs Left hand side of operation. + * \param rhs Right hand side of operation. + * \return Returns a constant vec4 object that is the results of lhs + rhs. + */ +const vec4 operator+( float lhs, const vec4 &rhs ) +{ + vec4 ret; + asm( "movaps %2, %%xmm1 \n\t" + "movss %1, %%xmm0 \n\t" + "shufps $0x00, %%xmm0, %%xmm0 \n\t" + "addps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(ret) + : "m"(lhs), "m"(rhs) + : "xmm0", "xmm1" + ); + return( ret ); +} + +/** + * \brief Uniary plus. + * + * Uniary plus, returns a copy of o. + * + * \param o Object to copy + * \return Returns a constant vec4 object that is the results of +o + */ +const vec4 operator+( const vec4 &o ) +{ + return( vec4( o )); +} + + +/** + * \brief Adds two vec4s. + * + * The method adds two vec4 objects togeather. Uses SSE. + * + * \param lhs Left hand side of operation. + * \param rhs Right hand side of operation. + * \return Returns lhs + rhs. + */ +vec4 & operator+=( vec4 &lhs, const vec4 &rhs ) +{ + asm( "movaps %1, %%xmm0 \n\t" + "movaps %2, %%xmm1 \n\t" + "addps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(lhs) + : "m"(lhs), "m"(rhs) + : "xmm0", "xmm1" + ); + return( lhs ); +} + +/** + * \brief Asss a vec4 by a scalar. + * + * the method adds a vec4 with a scalar Uses SSE. + * + * \param lhs Left hand side of operation. + * \param rhs Right hand side of operation. + * \return Returns lhs + rhs. + */ +vec4 & operator+=( vec4 &lhs, float rhs ) +{ + asm( "movaps %1, %%xmm0 \n\t" + "movss %2, %%xmm1 \n\t" + "shufps $0x00, %%xmm1, %%xmm1 \n\t" + "addps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(lhs) + : "m"(lhs), "m"(rhs) + : "xmm0", "xmm1" + ); + return( lhs ); +} + +/** + * \brief subtracts two vec4s. + * + * The method subs two vec4 objects togeather. Uses SSE. + * + * \param lhs Left hand side of operation. + * \param rhs Right hand side of operation. + * \return Returns a constant vec4 object that is the results of lhs - rhs. + */ +const vec4 operator-( const vec4 &lhs, const vec4 &rhs ) +{ + vec4 ret; + asm( "movaps %1, %%xmm0 \n\t" + "movaps %2, %%xmm1 \n\t" + "subps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(ret) + : "m"(lhs), "m"(rhs) + : "xmm0", "xmm1" + ); + return( ret ); +} + + +/** + * \brief Subtracts a Scalar to a vec4. + * + * The method subs a Scalar to a vec4. Uses SSE. + * + * \param lhs Left hand side of operation. + * \param rhs Right hand side of operation. + * \return Returns a constant vec4 object that is the results of lhs - rhs. + */ +const vec4 operator-( const vec4 &lhs, float rhs ) +{ + vec4 ret; + asm( "movaps %1, %%xmm0 \n\t" + "movss %2, %%xmm1 \n\t" + "shufps $0x00, %%xmm1, %%xmm1 \n\t" + "subps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(ret) + : "m"(lhs), "m"(rhs) + : "xmm0", "xmm1" + ); + return( ret ); +} + +/** + * \brief Subtracts Scalar to a vec4. + * + * The method subs a Scalar to a vec4. Uses SSE. + * + * \param lhs Left hand side of operation. + * \param rhs Right hand side of operation. + * \return Returns a constant vec4 object that is the results of lhs - rhs. + */ +const vec4 operator-( float lhs, const vec4 &rhs ) +{ + vec4 ret; + asm( "movaps %2, %%xmm1 \n\t" + "movss %1, %%xmm0 \n\t" + "shufps $0x00, %%xmm0, %%xmm0 \n\t" + "subps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(ret) + : "m"(lhs), "m"(rhs) + : "xmm0", "xmm1" + ); + return( ret ); +} + +/** + * \brief Uniary minus + * + * Uniary minus, returns a copy of o but negated + * + * \param o Object to copy and negate + * \return Returns a constant vec4 object that is the results of -o + */ +const vec4 operator-( const vec4 &o ) +{ + vec4 ret; + asm( "movaps %1, %%xmm1 \n\t" + "xorps %%xmm0, %%xmm0 \n\t" + "subps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(ret) + : "m"(o) + : "xmm0", "xmm1" + ); + return( ret ); +} + +/** + * \brief Subs two vec4s. + * + * The method subs two vec4 objects togeather. Uses SSE. + * + * \param lhs Left hand side of operation. + * \param rhs Right hand side of operation. + * \return Returns lhs - rhs. + */ +vec4 & operator-=( vec4 &lhs, const vec4 &rhs ) +{ + asm( "movaps %1, %%xmm0 \n\t" + "movaps %2, %%xmm1 \n\t" + "subps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(lhs) + : "m"(lhs), "m"(rhs) + : "xmm0", "xmm1" + ); + return( lhs ); +} + +/** + * \brief Subs a vec4 by a scalar. + * + * the method subs a vec4 with a scalar Uses SSE. + * + * \param lhs Left hand side of operation. + * \param rhs Right hand side of operation. + * \return Returns lhs - rhs. + */ +vec4 & operator-=( vec4 &lhs, float rhs ) +{ + asm( "movaps %1, %%xmm0 \n\t" + "movss %2, %%xmm1 \n\t" + "shufps $0x00, %%xmm1, %%xmm1 \n\t" + "subps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(lhs) + : "m"(lhs), "m"(rhs) + : "xmm0", "xmm1" + ); + return( lhs ); +} + +/** + * \brief Multiplies two vec4s. + * + * The method muls two vec4 objects togeather. Uses SSE. + * + * \param lhs Left hand side of operation. + * \param rhs Right hand side of operation. + * \return Returns a constant vec4 object that is the results of lhs * rhs. + */ +const vec4 operator*( const vec4 &lhs, const vec4 &rhs ) +{ + vec4 ret; + asm( "movaps %1, %%xmm0 \n\t" + "movaps %2, %%xmm1 \n\t" + "mulps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(ret) + : "m"(lhs), "m"(rhs) + : "xmm0", "xmm1" + ); + return( ret ); +} + + +/** + * \brief Multiplies a Scalar to a vec4. + * + * The method muls a Scalar to a vec4. Uses SSE. + * + * \param lhs Left hand side of operation. + * \param rhs Right hand side of operation. + * \return Returns a constant vec4 object that is the results of lhs * rhs. + */ +const vec4 operator*( const vec4 &lhs, float rhs ) +{ + vec4 ret; + asm( "movaps %1, %%xmm0 \n\t" + "movss %2, %%xmm1 \n\t" + "shufps $0x00, %%xmm1, %%xmm1 \n\t" + "mulps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(ret) + : "m"(lhs), "m"(rhs) + : "xmm0", "xmm1" + ); + return( ret ); +} + +/** + * \brief Subtracts Scalar to a vec4. + * + * The method muls a Scalar to a vec4. Uses SSE. + * + * \param lhs Left hand side of operation. + * \param rhs Right hand side of operation. + * \return Returns a constant vec4 object that is the results of lhs * rhs. + */ +const vec4 operator*( float lhs, const vec4 &rhs ) +{ + vec4 ret; + asm( "movaps %2, %%xmm1 \n\t" + "movss %1, %%xmm0 \n\t" + "shufps $0x00, %%xmm0, %%xmm0 \n\t" + "mulps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(ret) + : "m"(lhs), "m"(rhs) + : "xmm0", "xmm1" + ); + return( ret ); +} + + + +/** + * \brief muls two vec4s. + * + * the method muls two vec4 objects togeather. Uses SSE. + * + * \param lhs Left hand side of operation. + * \param rhs Right hand side of operation. + * \return Returns lhs * rhs. + */ +vec4 & operator*=( vec4 &lhs, const vec4 &rhs ) +{ + asm( "movaps %1, %%xmm0 \n\t" + "movaps %2, %%xmm1 \n\t" + "mulps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(lhs) + : "m"(lhs), "m"(rhs) + : "xmm0", "xmm1" + ); + return( lhs ); +} + +/** + * \brief Muls a vec4 by a scalar. + * + * the method mul a vec4 with a scalar Uses SSE. + * + * \param lhs Left hand side of operation. + * \param rhs Right hand side of operation. + * \return Returns lhs * rhs. + */ +vec4 & operator*=( vec4 &lhs, float rhs ) +{ + asm( "movaps %1, %%xmm0 \n\t" + "movss %2, %%xmm1 \n\t" + "shufps $0x00, %%xmm1, %%xmm1 \n\t" + "mulps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(lhs) + : "m"(lhs), "m"(rhs) + : "xmm0", "xmm1" + ); + return( lhs ); +} + +/** + * \brief Divides two vec4s. + * + * The method divs two vec4 objects togeather. Uses SSE. + * + * \param lhs Left hand side of operation. + * \param rhs Right hand side of operation. + * \return Returns a constant vec4 object that is the results of lhs / rhs. + */ +const vec4 operator/( const vec4 &lhs, const vec4 &rhs ) +{ + vec4 ret; + asm( "movaps %1, %%xmm0 \n\t" + "movaps %2, %%xmm1 \n\t" + "divps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(ret) + : "m"(lhs), "m"(rhs) + : "xmm0", "xmm1" + ); + return( ret ); +} + + +/** + * \brief Divides a Scalar to a vec4. + * + * The method divs a Scalar to a vec4. Uses SSE. + * + * \param lhs Left hand side of operation. + * \param rhs Right hand side of operation. + * \return Returns a constant vec4 object that is the results of lhs / rhs. + */ +const vec4 operator/( const vec4 &lhs, float rhs ) +{ + vec4 ret; + asm( "movaps %1, %%xmm0 \n\t" + "movss %2, %%xmm1 \n\t" + "shufps $0x00, %%xmm1, %%xmm1 \n\t" + "divps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(ret) + : "m"(lhs), "m"(rhs) + : "xmm0", "xmm1" + ); + return( ret ); +} + +/** + * \brief Divides Scalar to a vec4. + * + * The method divs a Scalar to a vec4. Uses SSE. + * + * \param lhs Left hand side of operation. + * \param rhs Right hand side of operation. + * \return Returns a constant vec4 object that is the results of lhs / rhs. + */ +const vec4 operator/( float lhs, const vec4 &rhs ) +{ + vec4 ret; + asm( "movaps %2, %%xmm1 \n\t" + "movss %1, %%xmm0 \n\t" + "shufps $0x00, %%xmm0, %%xmm0 \n\t" + "divps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(ret) + : "m"(lhs), "m"(rhs) + : "xmm0", "xmm1" + ); + return( ret ); +} + + +/** + * \brief Divs two vec4s. + * + * the method divs two vec4 objects togeather. Uses SSE. + * + * \param lhs Left hand side of operation. + * \param rhs Right hand side of operation. + * \return Returns lhs / rhs. + */ +vec4 & operator/=( vec4 &lhs, const vec4 &rhs ) +{ + asm( "movaps %1, %%xmm0 \n\t" + "movaps %2, %%xmm1 \n\t" + "divps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(lhs) + : "m"(lhs), "m"(rhs) + : "xmm0", "xmm1" + ); + return( lhs ); +} + +/** + * \brief Divs a vec4 by a scalar. + * + * the method divs two vec4 objects togeather. Uses SSE. + * + * \param lhs Left hand side of operation. + * \param rhs Right hand side of operation. + * \return Returns lhs / rhs. + */ +vec4 & operator/=( vec4 &lhs, float rhs ) +{ + asm( "movaps %1, %%xmm0 \n\t" + "movss %2, %%xmm1 \n\t" + "shufps $0x00, %%xmm1, %%xmm1 \n\t" + "divps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(lhs) + : "m"(lhs), "m"(rhs) + : "xmm0", "xmm1" + ); + return( lhs ); +} + +/** + * \brief Computes the dot product of two vectors, uses SSE. + * + * Computes the dot product of two vectors. The dot product is computed + * using SEE assembly instructions. Should be 32/64 portable. + * + * \param a A constant refrence to a vector struct. + * \param b A constant refrence to a vector struct. + * \return Single-precision dot product value. + */ +float dot( const vec4 &a, const vec4 &b ) +{ + register float ret = 0.0f; // Used to store the return value. + asm( "movaps %1, %%xmm0 \n\t" //vec4 is aligned, load the two vectors + "movaps %2, %%xmm1 \n\t" + "mulps %%xmm1, %%xmm0 \n\t" //x*x, y*y, z*z, w*w + "movaps %%xmm0, %%xmm1 \n\t" // copy xmm0 -> xmm1 + "shufps $0x4e, %%xmm1, %%xmm0 \n\t" // shuf 0100 1110 + "addps %%xmm1, %%xmm0 \n\t" // this add does half of the adding + "movaps %%xmm0, %%xmm1 \n\t" // recopy + "shufps $0x11, %%xmm1, %%xmm0 \n\t" // 0001 0001 + "addps %%xmm1, %%xmm0 \n\t" + "movss %%xmm0, %0\n\t" // mov lowest 4bytes into ret + : "=m"(ret) + : "m"( a ), "m"( b ) + : "xmm0", "xmm1" + ); + return ret; +} + +/** + * \brief Compute the cross product of vec4 a and b, returns a const vec4. + * + * This vecrion of cross produces a copy of a new cross product. This is + * a simpler way to use the cross product, but is slow since it makes copies. + * For real-time usage, use the other cross function. + * + * \param a First vec4 of the cross product. + * \param b Secound vec4 in the cross product. + * \return Returns a const copy of the cross product vec4. + */ +const vec4 cross( const vec4 &a, const vec4 &b ) +{ + /* + shufps XMM0, XMM0, 0xD8; + shufps XMM1, XMM1, 0xE1; + mulps XMM0, XMM1; + shufps XMM2, XMM2, 0xE1; + shufps XMM3, XMM3, 0xD8; + mulps XMM2, XMM3; + subps XMM0, XMM2; + movups t, XMM0; + */ + vec4 ret; + asm( "movaps %1, %%xmm0 \n\t" + "movaps %2, %%xmm1 \n\t" + "movaps %%xmm0, %%xmm2 \n\t" + "movaps %%xmm1, %%xmm3 \n\t" + "shufps $0xC9, %%xmm0, %%xmm0 \n\t" // y z x w 1001 1100 9C + "shufps $0xD2, %%xmm1, %%xmm1 \n\t" // z x y w 0111 1000 78 + "shufps $0xD2, %%xmm2, %%xmm2 \n\t" // 3 0 2 1 1100 1001 C9 + "shufps $0xC9, %%xmm3, %%xmm3 \n\t" // 3 1 0 2 1101 0010 D2 + "mulps %%xmm1, %%xmm0 \n\t" + "mulps %%xmm3, %%xmm2 \n\t" + "subps %%xmm2, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(ret) + : "m"( a ), "m"( b ) + : "xmm0", "xmm1", "xmm2", "xmm3" + ); + return( ret ); +} + +/** + * \brief Compute the cross product of vec4 a and b, puts the result in dest. + * + * Computes the cross product of a and b. The result is stored in dest vec4. + * This function if preferred over the other cross product function. This one is + * faster as it avoids extra copying. + * + * \param dest Holds the result of the cross product of a and b + * \param a First vec4 of the cross product. + * \param b Secound vec4 in the cross product. + * \return Returns the refrence to dest, useful for passing into other functions. + */ +vec4 &cross( vec4 &dest, const vec4 &a, const vec4 &b ) +{ + + return( dest ); +} + + +/** + \brief Clamp a color to min and max values + + Clamps a color vector to a set min and max value. This is used + to clamp a color to be used for rendering. + + \param c Color to clamp + \param min Min clamp value + \param max Max clamp value + \returns refrence to clamped color +*/ +color &clamp( color &c, const float min, const float max ) +{ + asm( "movaps %1, %%xmm0 \n\t" + "movss %2, %%xmm1 \n\t" + "shufps $0x00, %%xmm1, %%xmm1 \n\t" + "minps %%xmm1, %%xmm0 \n\t" + "movss %3, %%xmm1 \n\t" + "shufps $0x00, %%xmm1, %%xmm1 \n\t" + "maxps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(c) + : "m"(c), "m"(max), "m"(min) + : "xmm0", "xmm1" + ); + return( c ); +} + +/** + \brief Clamp a copied color to min and max values + + Clamps a color vector to a set min and max value. This is used + to clamp a color to be used for rendering. + + \param c Color to clamp + \param min Min clamp value + \param max Max clamp value + \returns refrence to copied clamped color +*/ +const color clamped( const color &c, const float min, const float max ) +{ + color ret; + asm( "movaps %1, %%xmm0 \n\t" + "movss %2, %%xmm1 \n\t" + "shufps $0x00, %%xmm1, %%xmm1 \n\t" + "minps %%xmm1, %%xmm0 \n\t" + "movss %3, %%xmm1 \n\t" + "shufps $0x00, %%xmm1, %%xmm1 \n\t" + "maxps %%xmm1, %%xmm0 \n\t" + "movaps %%xmm0, %0 \n\t" + : "=m"(ret) + : "m"(c), "m"(max), "m"(min) + : "xmm0", "xmm1" + ); + return( ret ); +} + diff --git a/rtrt/modules/vec_func.h b/rtrt/modules/vec_func.h new file mode 100644 index 0000000..17aca65 --- /dev/null +++ b/rtrt/modules/vec_func.h @@ -0,0 +1,60 @@ +/** + * \file vec_func.h + * \brief Prototypes for vector functions. + * + * Prototypes for vector functions. + * + * \see vec_func.cpp + * + * \author Byron Heads + */ + + +#ifndef VECT_FUNC_H +#define VECT_FUNC_H + +#include + +// Addition +const vec4 operator+( const vec4 &, const vec4 & ); +const vec4 operator+( const vec4 &, float ); +const vec4 operator+( float, const vec4 & ); +const vec4 operator+( const vec4 & ); +vec4 & operator +=( vec4 &, const vec4 & ); +vec4 & operator +=( vec4 &, float ); + +// Subtraction +const vec4 operator-( const vec4 &, const vec4 & ); +const vec4 operator-( const vec4 &, float ); +const vec4 operator-( float, const vec4 & ); +const vec4 operator-( const vec4 & ); +vec4 & operator -=( vec4 &, const vec4 & ); +vec4 & operator -=( vec4 &, float ); + +// Multiplication +const vec4 operator*( const vec4 &, const vec4 & ); +const vec4 operator*( const vec4 &, float ); +const vec4 operator*( float, const vec4 & ); +vec4 & operator *=( vec4 &, const vec4 & ); +vec4 & operator *=( vec4 &, float ); + +// Division +const vec4 operator/( const vec4 &, const vec4 & ); +const vec4 operator/( const vec4 &, float ); +const vec4 operator/( float, const vec4 & ); +vec4 & operator /=( vec4 &, const vec4 & ); +vec4 & operator /=( vec4 &, float ); + +// Products +float dot( const vec4 &, const vec4 & ); ///< Compute dot product of teo vectors +const vec4 cross( const vec4 &, const vec4 & ); ///< compute cross product as a new vec +vec4 &cross( vec4 &, const vec4 &, const vec4 & );///< compute cross into input param + +//color ops + +// color clamping +color &clamp( color &, const float = 0.0, const float = 1.0 ); /// < Clamp a color to a given value +const color clamped( const color &, const float = 0.0, const float = 1.0 ); /// < Return a clamped copy + +#endif + diff --git a/rtrt/modules/window.cpp b/rtrt/modules/window.cpp new file mode 100644 index 0000000..aaa2120 --- /dev/null +++ b/rtrt/modules/window.cpp @@ -0,0 +1,188 @@ +#include "window.h" + +Window::Window() + : running(false), framerate(0), framecount(0), framedelta(0.0), frameupdatetime(glfwGetTime() + 1.0), frameprev(glfwGetTime()) +{ + int major, minor, revision; + CHECK(glfwInit() == GL_TRUE) << "Failed to initilize GLFW"; + glfwGetVersion(&major, &minor, &revision); + LOG(INFO) << "Using GLFW verion " << major << "." << minor << "." << revision; + + windows().push_back(this); +} + +Window::Window(uint32_t width, uint32_t height, bool fullscreen, std::string title, int32_t interval) + : running(false), framerate(0), framecount(0), framedelta(0.0), frameupdatetime(glfwGetTime() + 1.0), frameprev(glfwGetTime()) +{ + int major, minor, revision; + glfwGetVersion(&major, &minor, &revision); + LOG(INFO) << "Using GLFW verion " << major << "." << minor << "." << revision; + CHECK(glfwInit() == GL_TRUE) << "Failed to initilize GLFW"; + + create_window(width, height, fullscreen, title, interval); + windows().push_back(this); +} + +Window::~Window() +{ + destroy_window(); + glfwTerminate(); +} + +void Window::create_window(uint32_t _width, uint32_t _height, bool _fullscreen, std::string title, int32_t interval) +{ + this->_width = _width; + this->_height = _height; + fullscreen = _fullscreen; + + glfwOpenWindowHint(GLFW_FSAA_SAMPLES, 0); // no AA + glfwOpenWindowHint(GLFW_WINDOW_NO_RESIZE, 1); // no resize + + LOG(INFO) << "Creating a " << (fullscreen ? "fullscreen " : "") << "window at " << _width << "x" << _height; + CHECK(glfwOpenWindow(_width, _height, 8, 8, 8, 0, 0, 0, (fullscreen ? GLFW_FULLSCREEN : GLFW_WINDOW)) == GL_TRUE) + << "GLFW Failed to create our window"; + change_title(title); + change_swap_interval(interval); + set_handlers(); + init_gl(); + running = true; +} + +void Window::change_title(std::string _title) +{ + title = _title; + glfwSetWindowTitle(title.c_str()); +} + +void Window::change_swap_interval(int32_t interval) +{ + LOG(INFO) << "Setting refreash interval to " << interval; + glfwSwapInterval( interval ); +} + +void Window::init_gl() +{ + glClearColor(0,0,0,0); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, _width, _height, 0, 0, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glDisable(GL_ALPHA); +} + +void Window::update_title_with_frame_rate() +{ + std::stringstream ss; + ss << title << ": " << framerate; + glfwSetWindowTitle(ss.str().c_str()); +} + +void Window::set_handlers() +{ + glfwSetWindowCloseCallback(&event_window_closed); + glfwSetWindowSizeCallback(&event_window_resized); + glfwSetWindowRefreshCallback(&event_window_refresh); + + glfwSetKeyCallback(&event_window_keypress); +} + +void Window::destroy_window() +{ + if( running ) glfwCloseWindow(); + running = false; +} + +int32_t Window::event_window_closed() +{ + int32_t ret = GL_FALSE; + BOOST_FOREACH( Window *win, windows()) + { + ret = ret || win->window_closed(); + } + return(GL_FALSE); +} + +void Window::event_window_refresh() +{ + BOOST_FOREACH( Window *win, windows()) + { + win->window_refresh(); + } +} + +void Window::event_window_resized(int _width, int _height) +{ + BOOST_FOREACH( Window *win, windows()) + { + win->window_resized(_width, _height); + } +} + +void Window::event_window_keypress(int _key, int _action) +{ + BOOST_FOREACH( Window *win, windows()) + { + win->window_keypress(_key, _action); + } +} + + +int32_t Window::window_closed() +{ + LOG(INFO) << "Got windows close event"; + running = false; + return(GL_FALSE); +} + +void Window::window_refresh() +{ + LOG(INFO) << "Got window refresh event"; +} + +void Window::window_resized(int _width, int _height) +{ + LOG(INFO) << "Got window resize event"; + _width = _width; + _height = _height; +} + +void Window::update_frame_rate() +{ + double frametime = glfwGetTime(); + ++framecount; + + if(frametime >= frameupdatetime) + { + framerate = framecount; + framecount = 0; + frameupdatetime = frametime + 1.0f; + } + + framedelta = frametime - frameprev; + frameprev = frametime; +} + +void Window::window_keypress(int key, int action) +{ + if(action == GLFW_PRESS) + { + if(key == GLFW_KEY_ESC || key == 'Q') + { + LOG(INFO) << "Got exit key"; + running = false; + } + } + else + { + + } +} + +void Window::render_image(Image &img) +{ + glDrawPixels(img.width(), img.height(), GL_RGBA, GL_UNSIGNED_BYTE, img.data()); +} diff --git a/rtrt/modules/window.h b/rtrt/modules/window.h new file mode 100644 index 0000000..d1b0251 --- /dev/null +++ b/rtrt/modules/window.h @@ -0,0 +1,69 @@ +#ifndef WINDOW_H +#define WINDOW_H + +// C++ includes +#include +#include +#include + +// Libraries +#include +#include +#include + +// Project +#include +#include + +class Window +{ +public: + Window(); + Window(uint32_t, uint32_t, bool, std::string, int32_t); + ~Window(); + + void create_window(uint32_t, uint32_t, bool, std::string, int32_t); + void change_title(std::string); + void change_swap_interval(int32_t); + void init_gl(); + void update_title_with_frame_rate(); + void destroy_window(); + + static int32_t event_window_closed(); + static void event_window_resized(int,int); + static void event_window_refresh(); + static void event_window_keypress(int, int); + + void render_image(Image &); + + inline bool is_running() { return(running); } + inline double delta() { return(framedelta); } + + inline void clear() { update_frame_rate(); glClear(GL_COLOR_BUFFER_BIT); } + inline void update() { glfwSwapBuffers(); } + + inline uint32_t width() { return(_width); } + inline uint32_t height(){ return(_height); } + +private: + uint32_t _width, _height; + bool fullscreen, running; + std::string title; + + int32_t framerate, framecount; + double framedelta, frameupdatetime, frameprev; + + + static std::vector &windows() { static std::vector s_vec; return(s_vec); } + + int32_t window_closed(); + void window_resized(int,int); + void window_refresh(); + void window_keypress(int,int); + + + void set_handlers(); + void update_frame_rate(); +}; + +#endif // WINDOW_H diff --git a/rtrt/rtrt.cpp b/rtrt/rtrt.cpp new file mode 100644 index 0000000..73b3dba --- /dev/null +++ b/rtrt/rtrt.cpp @@ -0,0 +1,55 @@ + +/** + @file rtrt.cpp + + @brief Real-time ray tracer main + + The real-time ray tracer is a thesis research project in the algorithms and data structures + need to create a real-time ray tracing render. + + @author Byron Heads + */ + +// C++ includes +#include + +// Projects includes +#include +#include +#include + +int main(int argc, char *argv[]) +{ + // process command line + parse_commandline(&argc, &argv); + + LOG(INFO) << "rtrt init"; + Window win(FLAGS_width, FLAGS_height, FLAGS_fullscreen, "Real-time Ray Tracer", FLAGS_interval); + Image img(win.width(), win.height()); // create the image + + while( win.is_running()) + { + win.clear(); // clear the back buffer, also computer frame rate and frame delta + if(FLAGS_fps) win.update_title_with_frame_rate(); // show the frame rate in the window title + + #pragma omp parallel for + for(size_t y = 0; y < img.height(); ++y) + { + for(size_t x = 0; x < img.width(); ++x) + { + img.set(x,y,color(1,0,0)); + } + } + + + win.render_image(img); // render the image to the back buffer + + win.update(); // swap the back buffer with the front buffer + } + + LOG(INFO) << "shutting down"; + img.destroy_image(); + win.destroy_window(); + + return(0); +} diff --git a/rtrt/rtrt.pro b/rtrt/rtrt.pro new file mode 100644 index 0000000..3b3134e --- /dev/null +++ b/rtrt/rtrt.pro @@ -0,0 +1,30 @@ + +QMAKE_CXXFLAGS += -sse -sse2 -fopenmp + +LIBS += -lgomp -lgflags -lglog -framework Cocoa -framework AGL -framework OpenGL -lglfw + +QT -= core gui + +SOURCES += \ + rtrt.cpp \ + modules/cmdflags.cpp \ + modules/window.cpp \ + modules/image.cpp \ + modules/vec_func.cpp + +HEADERS += \ + cmdflags.h \ + modules/window.h \ + modules/image.h \ + modules/vec4.h \ + modules/vec_func.h + + + + + + + + + + diff --git a/rtrt/rtrt.pro.user b/rtrt/rtrt.pro.user new file mode 100644 index 0000000..9bb9bd7 --- /dev/null +++ b/rtrt/rtrt.pro.user @@ -0,0 +1,300 @@ + + + + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + + Cpp + + false + CppGlobal + true + false + true + false + false + false + true + true + false + true + false + false + false + true + false + + + 1 + System + Global + 4 + true + 1 + true + false + true + + Cpp + + true + false + CppGlobal + 4 + 1 + false + true + 0 + 8 + + + + QmlJS + + true + false + QmlJSGlobal + 4 + 1 + false + true + 0 + 8 + + + 2 + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + Qt4ProjectManager.Target.DesktopTarget + 0 + 0 + 0 + + ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-macos-generic-mach_o-64bit./usr/bin/gdb + + + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + Make + + Qt4ProjectManager.MakeStep + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + Make + + Qt4ProjectManager.MakeStep + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Desktop Qt 4.7.3 for GCC (Qt SDK) Debug + + Qt4ProjectManager.Qt4BuildConfiguration + 2 + /Users/byron/github/rtrt_thesis/rtrt-build-desktop-Desktop_Qt_4_7_3_for_GCC__Qt_SDK__Debug + 2 + true + + + ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-macos-generic-mach_o-64bit./usr/bin/gdb + + + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + Make + + Qt4ProjectManager.MakeStep + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + Make + + Qt4ProjectManager.MakeStep + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Desktop Qt 4.7.3 for GCC (Qt SDK) Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + /Users/byron/github/rtrt_thesis/rtrt-build-desktop-Desktop_Qt_4_7_3_for_GCC__Qt_SDK__Release + 2 + true + + 2 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + No deployment + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + true + true + + + false + false + false + false + false + false + false + false + true + true + 0.01 + 0.01 + 10 + 10 + true + true + 25 + 25 + + + true + true + valgrind + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + rtrt + + Qt4ProjectManager.Qt4RunConfiguration + 2 + + rtrt.pro + false + false + + + 3768 + true + false + false + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.EnvironmentId + {523afb62-6e67-4116-a454-7aa05232fe91} + + + ProjectExplorer.Project.Updater.FileVersion + 10 + + diff --git a/src/main.cpp b/src/main.cpp index 175845f..e838137 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -137,7 +137,7 @@ int rtrt_main() glClear( GL_COLOR_BUFFER_BIT ); // do work here, replace this with the ray tracer - //img._fill_random(); + img._fill_random(); ray._render( img.Data(), FLAGS_width, FLAGS_height ); // render image to frame buffer diff --git a/src/util/image/image.cpp b/src/util/image/image.cpp index b0a670c..23a4e65 100644 --- a/src/util/image/image.cpp +++ b/src/util/image/image.cpp @@ -76,9 +76,6 @@ namespace rt { // draw the image pixels, slow.... glDrawPixels( width, height, GL_RGBA, GL_FLOAT, data ); - - - } } diff --git a/src/util/rt/rt.cpp b/src/util/rt/rt.cpp index 3ebdbbb..90c65b4 100644 --- a/src/util/rt/rt.cpp +++ b/src/util/rt/rt.cpp @@ -21,9 +21,9 @@ namespace rt void RayTracer::_render( color *img, size_t width, size_t height ) { #pragma omp parallel for - for( size_t y = 0; y < height; ++y ) + for( ssize_t y = 0; y < height; ++y ) { - for( size_t x = 0; x < width; ++ x ) + for( ssize_t x = 0; x < width; ++ x ) { // get the current color color &c = img[ ( y * width ) + x ];