- GLEW es una librería que en tiempo de ejecución determina que extensiones de OpenGL son soportadas por el cliente.
- Página referencia en el sitio OpenGL: http://www.opengl.org/sdk/libs/GLEW/
- Sitio Web oficial: http://glew.sourceforge.net/
- GL3W librería que carga solo la funcionalidad básica de OpenGL 3/4.
Esta librería se puede obtener directamente desde GitHub y hace falta Python para compilar el script que te descargas. Sólo hace falta para generar el script, después lo podemos desinstalar: https://github.com/skaslev/gl3w - vmath y el cargador de shaders son dos herramientas que he obtenido con el set de ejemplos del libro: "OpenGL Programming Guide. Eight Edition"
Se trata de dos librerías que, facilitan las operaciones con vectores y matrices (vmath) y la carga de shaders (LoadShaders). El código de las mismas es el siguiente:
vmath.h#ifndef __VMATH_H__ #define __VMATH_H__ #define _USE_MATH_DEFINES 1 // Include constants defined in math.h #include <math.h> namespace vmath { template <typename T> inline T radians(T angleInRadians) { return angleInRadians * static_cast<T>(180.0/M_PI); } template <const bool cond> class ensure { public: inline ensure() { switch (false) { case false: case cond: break; } } }; template <typename T, const int len> class vecN; template <typename T, const int len> class vecN { public: typedef class vecN<T,len> my_type; // Default constructor does nothing, just like built-in types inline vecN() { // Uninitialized variable } // Copy constructor inline vecN(const vecN& that) { assign(that); } // Construction from scalar inline vecN(T s) { int n; for (n = 0; n < len; n++) { data[n] = s; } } // Assignment operator inline vecN& operator=(const vecN& that) { assign(that); return *this; } inline vecN operator+(const vecN& that) const { my_type result; int n; for (n = 0; n < len; n++) result.data[n] = data[n] + that.data[n]; return result; } inline vecN& operator+=(const vecN& that) { return (*this = *this + that); } inline vecN operator-() const { my_type result; int n; for (n = 0; n < len; n++) result.data[n] = -data[n]; return result; } inline vecN operator-(const vecN& that) const { my_type result; int n; for (n = 0; n < len; n++) result.data[n] = data[n] - that.data[n]; return result; } inline vecN& operator-=(const vecN& that) { return (*this = *this - that); } inline vecN operator*(const vecN& that) const { my_type result; int n; for (n = 0; n < len; n++) result.data[n] = data[n] * that.data[n]; return result; } inline vecN& operator*=(const vecN& that) { return (*this = *this * that); } inline vecN operator*(const T& that) const { my_type result; int n; for (n = 0; n < len; n++) result.data[n] = data[n] * that; return result; } inline vecN& operator*=(const T& that) { assign(*this * that); return *this; } inline vecN operator/(const vecN& that) const { my_type result; int n; for (n = 0; n < len; n++) result.data[n] = data[n] * that.data[n]; return result; } inline vecN& operator/=(const vecN& that) { assign(*this * that); return *this; } inline vecN operator/(const T& that) const { my_type result; int n; for (n = 0; n < len; n++) result.data[n] = data[n] / that; return result; } inline vecN& operator/(const T& that) { assign(*this / that); } inline T& operator[](int n) { return data[n]; } inline const T& operator[](int n) const { return data[n]; } inline static int size(void) { return len; } inline operator const T* () const { return &data[0]; } protected: T data[len]; inline void assign(const vecN& that) { int n; for (n = 0; n < len; n++) data[n] = that.data[n]; } }; template <typename T> class Tvec2 : public vecN<T,2> { public: typedef vecN<T,2> base; // Uninitialized variable inline Tvec2() {} // Copy constructor inline Tvec2(const base& v) : base(v) {} // vec2(x, y); inline Tvec2(T x, T y) { base::data[0] = x; base::data[1] = y; } }; template <typename T> class Tvec3 : public vecN<T,3> { public: typedef vecN<T,3> base; // Uninitialized variable inline Tvec3() {} // Copy constructor inline Tvec3(const base& v) : base(v) {} // vec3(x, y, z); inline Tvec3(T x, T y, T z) { base::data[0] = x; base::data[1] = y; base::data[2] = z; } // vec3(v, z); inline Tvec3(const Tvec2<T>& v, T z) { base::data[0] = v[0]; base::data[1] = v[1]; base::data[2] = z; } // vec3(x, v) inline Tvec3(T x, const Tvec2<T>& v) { base::data[0] = x; base::data[1] = v[0]; base::data[2] = v[1]; } }; template <typename T> class Tvec4 : public vecN<T,4> { public: typedef vecN<T,4> base; // Uninitialized variable inline Tvec4() {} // Copy constructor inline Tvec4(const base& v) : base(v) {} // vec4(x, y, z, w); inline Tvec4(T x, T y, T z, T w) { base::data[0] = x; base::data[1] = y; base::data[2] = z; base::data[3] = w; } // vec4(v, z, w); inline Tvec4(const Tvec2<T>& v, T z, T w) { base::data[0] = v[0]; base::data[1] = v[1]; base::data[2] = z; base::data[3] = w; } // vec4(x, v, w); inline Tvec4(T x, const Tvec2<T>& v, T w) { base::data[0] = x; base::data[1] = v[0]; base::data[2] = v[1]; base::data[3] = w; } // vec4(x, y, v); inline Tvec4(T x, T y, const Tvec2<T>& v) { base::data[0] = x; base::data[1] = y; base::data[2] = v[0]; base::data[3] = v[1]; } // vec4(v1, v2); inline Tvec4(const Tvec2<T>& u, const Tvec2<T>& v) { base::data[0] = u[0]; base::data[1] = u[1]; base::data[2] = v[0]; base::data[3] = v[1]; } // vec4(v, w); inline Tvec4(const Tvec3<T>& v, T w) { base::data[0] = v[0]; base::data[1] = v[1]; base::data[2] = v[2]; base::data[3] = w; } // vec4(x, v); inline Tvec4(T x, const Tvec3<T>& v) { base::data[0] = x; base::data[1] = v[0]; base::data[2] = v[1]; base::data[3] = v[2]; } }; typedef Tvec2<float> vec2; typedef Tvec2<int> ivec2; typedef Tvec2<unsigned int> uvec2; typedef Tvec2<double> dvec2; typedef Tvec3<float> vec3; typedef Tvec3<int> ivec3; typedef Tvec3<unsigned int> uvec3; typedef Tvec3<double> dvec3; typedef Tvec4<float> vec4; typedef Tvec4<int> ivec4; typedef Tvec4<unsigned int> uvec4; typedef Tvec4<double> dvec4; template <typename T, int n> static inline const vecN<T,n> operator * (T x, const vecN<T,n>& v) { return v * x; } template <typename T> static inline const Tvec2<T> operator / (T x, const Tvec2<T>& v) { return Tvec2<T>(x / v[0], x / v[1]); } template <typename T> static inline const Tvec3<T> operator / (T x, const Tvec3<T>& v) { return Tvec3<T>(x / v[0], x / v[1], x / v[2]); } template <typename T> static inline const Tvec4<T> operator / (T x, const Tvec4<T>& v) { return Tvec4<T>(x / v[0], x / v[1], x / v[2], x / v[3]); } template <typename T, int len> static inline T dot(const vecN<T,len>& a, const vecN<T,len>& b) { int n; T total = T(0); for (n = 0; n < len; n++) { total += a[n] * b[n]; } return total; } template <typename T> static inline vecN<T,3> cross(const vecN<T,3>& a, const vecN<T,3>& b) { return Tvec3<T>(a[1] * b[2] - b[1] * a[2], a[2] * b[0] - b[2] * a[0], a[0] * b[1] - b[0] * a[1]); } template <typename T, int len> static inline T length(const vecN<T,len>& v) { T result(0); for (int i = 0; i < v.size(); ++i) { result += v[i] * v[i]; } return (T)sqrt(result); } template <typename T, int len> static inline vecN<T,len> normalize(const vecN<T,len>& v) { return v / length(v); } template <typename T, int len> static inline T distance(const vecN<T,len>& a, const vecN<T,len>& b) { return length(b - a); } template <typename T, const int w, const int h> class matNM { public: typedef class matNM<T,w,h> my_type; typedef class vecN<T,h> vector_type; // Default constructor does nothing, just like built-in types inline matNM() { // Uninitialized variable } // Copy constructor inline matNM(const matNM& that) { assign(that); } // Construction from element type // explicit to prevent assignment from T explicit inline matNM(T f) { for (int n = 0; n < w; n++) { data[n] = f; } } // Construction from vector inline matNM(const vector_type& v) { for (int n = 0; n < w; n++) { data[n] = v; } } // Assignment operator inline matNM& operator=(const my_type& that) { assign(that); return *this; } inline matNM operator+(const my_type& that) const { my_type result; int n; for (n = 0; n < w; n++) result.data[n] = data[n] + that.data[n]; return result; } inline my_type& operator+=(const my_type& that) { return (*this = *this + that); } inline my_type operator-(const my_type& that) const { my_type result; int n; for (n = 0; n < w; n++) result.data[n] = data[n] - that.data[n]; return result; } inline my_type& operator-=(const my_type& that) { return (*this = *this - that); } // Matrix multiply. // TODO: This only works for square matrices. Need more template skill to make a non-square version. inline my_type operator*(const my_type& that) const { ensure<w == h>(); my_type result(0); for (int j = 0; j < w; j++) { for (int i = 0; i < h; i++) { T sum(0); for (int n = 0; n < w; n++) { sum += data[n][i] * that[j][n]; } result[j][i] = sum; } } return result; } inline my_type& operator*=(const my_type& that) { return (*this = *this * that); } inline vector_type& operator[](int n) { return data[n]; } inline const vector_type& operator[](int n) const { return data[n]; } inline operator T*() { return &data[0][0]; } inline operator const T*() const { return &data[0][0]; } inline matNM<T,h,w> transpose(void) const { matNM<T,h,w> result; int x, y; for (y = 0; y < w; y++) { for (x = 0; x < h; x++) { result[x][y] = data[y][x]; } } return result; } static inline my_type identity() { ensure<w == h>(); my_type result(0); for (int i = 0; i < w; i++) { result[i][i] = 1; } return result; } static inline int width(void) { return w; } static inline int height(void) { return h; } protected: // Column primary data (essentially, array of vectors) vecN<T,h> data[w]; // Assignment function - called from assignment operator and copy constructor. inline void assign(const matNM& that) { int n; for (n = 0; n < w; n++) data[n] = that.data[n]; } }; /* template <typename T, const int N> class TmatN : public matNM<T,N,N> { public: typedef matNM<T,N,N> base; typedef TmatN<T,N> my_type; inline TmatN() {} inline TmatN(const my_type& that) : base(that) {} inline TmatN(float f) : base(f) {} inline TmatN(const vecN<T,4>& v) : base(v) {} inline my_type transpose(void) { my_type result; int x, y; for (y = 0; y < h; y++) { for (x = 0; x < h; x++) { result[x][y] = data[y][x]; } } return result; } }; */ template <typename T> class Tmat4 : public matNM<T,4,4> { public: typedef matNM<T,4,4> base; typedef Tmat4<T> my_type; inline Tmat4() {} inline Tmat4(const my_type& that) : base(that) {} inline Tmat4(const base& that) : base(that) {} inline Tmat4(const vecN<T,4>& v) : base(v) {} inline Tmat4(const vecN<T,4>& v0, const vecN<T,4>& v1, const vecN<T,4>& v2, const vecN<T,4>& v3) { base::data[0] = v0; base::data[1] = v1; base::data[2] = v2; base::data[3] = v3; } }; typedef Tmat4<float> mat4; typedef Tmat4<int> imat4; typedef Tmat4<unsigned int> umat4; typedef Tmat4<double> dmat4; static inline mat4 frustum(float left, float right, float bottom, float top, float n, float f) { mat4 result(mat4::identity()); if ((right == left) || (top == bottom) || (n == f) || (n < 0.0) || (f < 0.0)) return result; result[0][0] = (2.0f * n) / (right - left); result[1][1] = (2.0f * n) / (top - bottom); result[2][0] = (right + left) / (right - left); result[2][1] = (top + bottom) / (top - bottom); result[2][2] = -(f + n) / (f - n); result[2][3]= -1.0f; result[3][2] = -(2.0f * f * n) / (f - n); result[3][3] = 0.0f; return result; } static inline mat4 perspective(float fovy /* in degrees */, float aspect, float n, float f) { float top = n * tan(radians(0.5f*fovy)); // bottom = -top float right = top * aspect; // left = -right return frustum(-right, right, -top, top, n, f); } template <typename T> static inline Tmat4<T> lookat(vecN<T,3> eye, vecN<T,3> center, vecN<T,3> up) { const Tvec3<T> f = normalize(center - eye); const Tvec3<T> upN = normalize(up); const Tvec3<T> s = cross(f, upN); const Tvec3<T> u = cross(s, f); const Tmat4<T> M = Tmat4<T>(Tvec4<T>(s[0], u[0], -f[0], T(0)), Tvec4<T>(s[1], u[1], -f[1], T(0)), Tvec4<T>(s[2], u[2], -f[2], T(0)), Tvec4<T>(T(0), T(0), T(0), T(1))); return M * translate(-eye); } template <typename T> static inline Tmat4<T> translate(T x, T y, T z) { return Tmat4<T>(Tvec4<T>(1.0f, 0.0f, 0.0f, 0.0f), Tvec4<T>(0.0f, 1.0f, 0.0f, 0.0f), Tvec4<T>(0.0f, 0.0f, 1.0f, 0.0f), Tvec4<T>(x, y, z, 1.0f)); } template <typename T> static inline Tmat4<T> translate(const vecN<T,3>& v) { return translate(v[0], v[1], v[2]); } template <typename T> static inline Tmat4<T> scale(T x, T y, T z) { return Tmat4<T>(Tvec4<T>(x, 0.0f, 0.0f, 0.0f), Tvec4<T>(0.0f, y, 0.0f, 0.0f), Tvec4<T>(0.0f, 0.0f, z, 0.0f), Tvec4<T>(0.0f, 0.0f, 0.0f, 1.0f)); } template <typename T> static inline Tmat4<T> scale(const Tvec4<T>& v) { return scale(v[0], v[1], v[2]); } template <typename T> static inline Tmat4<T> scale(T x) { return Tmat4<T>(Tvec4<T>(x, 0.0f, 0.0f, 0.0f), Tvec4<T>(0.0f, x, 0.0f, 0.0f), Tvec4<T>(0.0f, 0.0f, x, 0.0f), Tvec4<T>(0.0f, 0.0f, 0.0f, 1.0f)); } template <typename T> static inline Tmat4<T> rotate(T angle, T x, T y, T z) { Tmat4<T> result; const T x2 = x * x; const T y2 = y * y; const T z2 = z * z; float rads = float(angle) * 0.0174532925f; const float c = cosf(rads); const float s = sinf(rads); const float omc = 1.0f - c; result[0] = Tvec4<T>(T(x2 * omc + c), T(y * x * omc + z * s), T(x * z * omc - y * s), T(0)); result[1] = Tvec4<T>(T(x * y * omc - z * s), T(y2 * omc + c), T(y * z * omc + x * s), T(0)); result[2] = Tvec4<T>(T(x * z * omc + y * s), T(y * z * omc - x * s), T(z2 * omc + c), T(0)); result[3] = Tvec4<T>(T(0), T(0), T(0), T(1)); return result; } template <typename T> static inline Tmat4<T> rotate(T angle, const vecN<T,3>& v) { return rotate<T>(angle, v[0], v[1], v[2]); } #ifdef min #undef min #endif template <typename T> static inline T min(T a, T b) { return a < b ? a : b; } #ifdef max #undef max #endif template <typename T> static inline T max(T a, T b) { return a >= b ? a : b; } template <typename T, const int N> static inline vecN<T,N> min(const vecN<T,N>& x, const vecN<T,N>& y) { vecN<T,N> t; int n; for (n = 0; n < N; n++) { t[n] = min(x[n], y[n]); } return t; } template <typename T, const int N> static inline vecN<T,N> max(const vecN<T,N>& x, const vecN<T,N>& y) { vecN<T,N> t; int n; for (n = 0; n < N; n++) { t[n] = max<T>(x[n], y[n]); } return t; } template <typename T, const int N> static inline vecN<T,N> clamp(const vecN<T,N>& x, const vecN<T,N>& minVal, const vecN<T,N>& maxVal) { return min<T>(max<T>(x, minVal), maxVal); } template <typename T, const int N> static inline vecN<T,N> smoothstep(const vecN<T,N>& edge0, const vecN<T,N>& edge1, const vecN<T,N>& x) { vecN<T,N> t; t = clamp((x - edge0) / (edge1 - edge0), vecN<T,N>(T(0)), vecN<T,N>(T(1))); return t * t * (vecN<T,N>(T(3)) - vecN<T,N>(T(2)) * t); } template <typename T, const int N, const int M> static inline matNM<T,N,M> matrixCompMult(const matNM<T,N,M>& x, const matNM<T,N,M>& y) { matNM<T,N,M> result; int i, j; for (j = 0; j < M; ++j) { for (i = 0; i < N; ++i) { result[i][j] = x[i][j] * y[i][j]; } } return result; } template <typename T, const int N, const int M> static inline vecN<T,N> operator*(const vecN<T,M>& vec, const matNM<T,N,M>& mat) { int n, m; vecN<T,N> result(T(0)); for (m = 0; m < M; m++) { for (n = 0; n < N; n++) { result[n] += vec[m] * mat[n][m]; } } return result; } }; #endif /* __VMATH_H__ */
LoadShaders.h////////////////////////////////////////////////////////////////////////////// // // --- LoadShaders.h --- // ////////////////////////////////////////////////////////////////////////////// #ifndef __LOAD_SHADERS_H__ #define __LOAD_SHADERS_H__ #include <GL/gl.h> #ifdef __cplusplus extern "C" { #endif // __cplusplus //---------------------------------------------------------------------------- // // LoadShaders() takes an array of ShaderFile structures, each of which // contains the type of the shader, and a pointer a C-style character // string (i.e., a NULL-terminated array of characters) containing the // entire shader source. // // The array of structures is terminated by a final Shader with the // "type" field set to GL_NONE. // // LoadShaders() returns the shader program value (as returned by // glCreateProgram()) on success, or zero on failure. // typedef struct { GLenum type; const char* filename; GLuint shader; } ShaderInfo; GLuint LoadShaders( ShaderInfo* ); //---------------------------------------------------------------------------- #ifdef __cplusplus }; #endif // __cplusplus #endif // __LOAD_SHADERS_H__
LoadShaders.cpp////////////////////////////////////////////////////////////////////////////// // // --- LoadShaders.cxx --- // ////////////////////////////////////////////////////////////////////////////// #include <cstdlib> #include <iostream> #include <cstdio> #define GLEW_STATIC #include <GL/glew.h> #include "LoadShaders.h" #ifdef __cplusplus extern "C" { #endif // __cplusplus //---------------------------------------------------------------------------- static const GLchar* ReadShader( const char* filename ) { FILE* infile = fopen( filename, "rb" ); if ( !infile ) { #ifdef _DEBUG std::cerr << "Unable to open file '" << filename << "'" << std::endl; #endif /* DEBUG */ return NULL; } fseek( infile, 0, SEEK_END ); int len = ftell( infile ); fseek( infile, 0, SEEK_SET ); GLchar* source = new GLchar[len+1]; fread( source, 1, len, infile ); fclose( infile ); source[len] = 0; return const_cast<const GLchar*>(source); } //---------------------------------------------------------------------------- GLuint LoadShaders( ShaderInfo* shaders ) { if(glewInit()){ std::cerr << "Unable to initialize GLEW..." << std::endl; } if ( shaders == NULL ) { return 0; } GLuint program = glCreateProgram(); ShaderInfo* entry = shaders; while ( entry->type != GL_NONE ) { GLuint shader = glCreateShader( entry->type ); entry->shader = shader; const GLchar* source = ReadShader( entry->filename ); if ( source == NULL ) { for ( entry = shaders; entry->type != GL_NONE; ++entry ) { glDeleteShader( entry->shader ); entry->shader = 0; } return 0; } glShaderSource( shader, 1, &source, NULL ); delete [] source; glCompileShader( shader ); GLint compiled; glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled ); if ( !compiled ) { #ifdef _DEBUG GLsizei len; glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &len ); GLchar* log = new GLchar[len+1]; glGetShaderInfoLog( shader, len, &len, log ); std::cerr << "Shader compilation failed: " << log << std::endl; delete [] log; #endif /* DEBUG */ return 0; } glAttachShader( program, shader ); ++entry; } #ifdef GL_VERSION_4_1 if ( GLEW_VERSION_4_1 ) { // glProgramParameteri( program, GL_PROGRAM_SEPARABLE, GL_TRUE ); } #endif /* GL_VERSION_4_1 */ glLinkProgram( program ); GLint linked; glGetProgramiv( program, GL_LINK_STATUS, &linked ); if ( !linked ) { #ifdef _DEBUG GLsizei len; glGetProgramiv( program, GL_INFO_LOG_LENGTH, &len ); GLchar* log = new GLchar[len+1]; glGetProgramInfoLog( program, len, &len, log ); std::cerr << "Shader linking failed: " << log << std::endl; delete [] log; #endif /* DEBUG */ for ( entry = shaders; entry->type != GL_NONE; ++entry ) { glDeleteShader( entry->shader ); entry->shader = 0; } return 0; } return program; } //---------------------------------------------------------------------------- #ifdef __cplusplus } #endif // __cplusplus
No se si son las mejores pero nos vienen al pelo.
Ademas, hay que cambiar las opciones de las librerías incluidas en el proyecto, ahora hay que añadir: glew32. El orden de inclusión importa por lo que copio, pego y modifico el que ya teníamos en el post de configuración de Eclipse.
- mingw32
- glew32
- opengl32
- SDL2main
- SDL2
No hay comentarios:
Publicar un comentario