///////////////////////////////////////////////////////////////////////////// // Name: oglstuff.h // Purpose: OpenGL manager for pyramid sample // Author: Manuel Martin // Created: 2015/01/31 // Copyright: (c) 2015 Manuel Martin // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef OGLSTUFF_H #define OGLSTUFF_H #include #include #include "mathstuff.h" // This file allows access to OpenGL functions used in this sample. #include "oglpfuncs.h" /* ************ NOTES ******************************************************* This is not an OGL tutorial, I mean, this is just a sample of how OGL stuff may be arranged. I tried to keep it simple. It's likely that the novice to OGL reads this sample, so here are some brief notes: * Starting with OpenGL >= 2.0 the user defines some special programs that are going to be executed in the GPU, not in the CPU. These programs are called "Shaders". Since OGL >= 3.2, and if a "Core Profile" context is set, the use of shaders is the only way to make an OGL application. * A program consists (at least) of a 'vertex shader' who operates on the vertices that define the primitive (a triangle, a line, etc) and a 'fragment shader' which deals with fragments (points) interpolated from the previously processed vertices in the vertex shader. * Shaders must be compiled and linked, both operations are done on the GPU. * Shaders are written in the GLSL language, that looks like C, but it isn't C. * Data (vertices, textures) are stored in GPU memory, so they don't need to be loaded each time the scene must be redrawn. * Rotations and translations are matrix operations that the GPU may do in the [vertex]shaders. The user must define the needed matrices. * A vertex shader defines special vars ("attributes") used for reading the data from the GPU buffers. Other special vars ("uniforms") are used for values that don't change with each vertex (i.e. the matrices). * The relationship between a data buffer and the input attributes in a vertex shader can be saved in a "Vertex Array Object" (VAO). I use several classes for typical OGL jobs: Shaders, Data, Camera. Because different GPU cards may behave on their own, I also use very often an error-helper. It will inform of the point where something went wrong. I decided to keep apart all of this from wxWidgets. You won't find anything related to wxWidgets in the oglstuff[.h][.cpp] files. That's why I use std::vector and std::string instead of those provided by wx. */ // Define our own GL errors enum { myoglERR_CLEAR = 0, myoglERR_JUSTLOG, myoglERR_SHADERCREATE, myoglERR_SHADERCOMPILE, myoglERR_SHADERLINK, myoglERR_SHADERLOCATION, myoglERR_BUFFER, myoglERR_TEXTIMAGE, myoglERR_DRAWING_TRI, myoglERR_DRAWING_STR }; // Used to handle GL errors in other part of the app. typedef void myOGLErrHandler(int err, int glerr, const GLchar* glMsg); // For shader attributes struct shaVars { GLuint loc; //The attribute "location", some kind of index in the shader std::string name; //The name of the attribute }; typedef std::vector shaVars_v; // For shader code struct shaShas { GLuint shaId; GLenum typeSha; //The type of shader const GLchar* scode; //The NULL terminated GLSL code }; typedef std::vector shaShas_v; //----------------------------------------------------------------------------- // This object builds a GPU program by joining several shaders. class myOGLShaders { public: myOGLShaders(); ~myOGLShaders(); void Init(); bool Use(); void StopUse(); void CleanUp(); void AddCode(const GLchar* shaString, GLenum shaType); void AddAttrib(const std::string& name); void AddUnif(const std::string& name); GLuint GetAttribLoc(const std::string& name); GLuint GetUnifLoc(const std::string& name); // Disable generic vertex attribute array void DisableGenericVAA(); private: void SetAttribLocations(); bool AskUnifLocations(); bool Compile(GLuint shaId); bool LinkProg(GLuint proId); shaVars_v m_shaAttrib; // 'attributes' names and locations shaVars_v m_shaUnif; // 'uniforms' names and locations shaShas_v m_shaCode; // shaders code and their types GLuint m_proId; // program Id bool m_SHAinitializated; }; //----------------------------------------------------------------------------- // A "point light" class myLight { public: myLight() {} ~myLight() {} void Set(const myVec3& position, GLfloat intensity, GLfloat R, GLfloat G, GLfloat B); // Return position and intensity const GLfloat* GetFLightPos() const { return m_PosAndIntensisty; } // Return colour const GLfloat* GetFLightColour() const { return m_Colour; } private: // Light position and intensity GLfloat m_PosAndIntensisty[4]; // Light colour GLfloat m_Colour[3]; }; //----------------------------------------------------------------------------- // An object for triangles class myOGLTriangles { public: myOGLTriangles(); ~myOGLTriangles(); // Clean up void Clear(); // Load data into the GPU void SetBuffers(myOGLShaders* theShader, GLsizei nuPoints, GLsizei nuTriangs, const GLfloat* vert, const GLfloat* colo, const GLfloat* norm, const GLushort* indices); //Draw the triangles void Draw(const GLfloat* unifMvp, const GLfloat* unifToVw, const myLight* theLight); private: GLsizei m_nuTriangs; // Buffers ids GLuint m_bufVertId; GLuint m_bufColNorId; GLuint m_bufIndexId; // Vertex Arrays Object GLuint m_triangVAO; // GPU Program used to draw the triangles myOGLShaders* m_triangShaders; }; //----------------------------------------------------------------------------- // An object for strings class myOGLString { public: myOGLString(); ~myOGLString(); // Clean up void Clear(); // Load data into the GPU void SetStringWithVerts(myOGLShaders* theShader, const unsigned char* tImage, int tWidth, int tHeigh, const GLfloat* vert, const GLfloat* norm); // Draw the string void Draw(const GLfloat* unifMvp, const GLfloat* unifToVw, const myLight* theLight); private: GLuint m_bufPosId; // Buffer id GLuint m_stringVAO; // Vertex Arrays Object GLuint m_textureUnit; // The context unit GLuint m_textureId; // Texture name // GPU Program used to draw the texture myOGLShaders* m_stringShaders; }; //----------------------------------------------------------------------------- // An object for the immutable string class myOGLImmutString : public myOGLString { public: myOGLImmutString(){} ~myOGLImmutString(){} // Load data into the GPU void SetImmutString(myOGLShaders* theShader, const unsigned char* tImage, int tWidth, int tHeigh); // Update orthogonal projection matrix void SetOrtho(int winWidth, int winHeight); // The transformation matrix const GLfloat* GetFloatMVP() { return m_fOrtho; } private: double m_dOrtho[16]; // The orthogonal projection matrix GLfloat m_fOrtho[16]; // Same as float }; //----------------------------------------------------------------------------- // The "camera", or the point of view class myOGLCamera { public: myOGLCamera(); ~myOGLCamera() {} // Initial positions void InitPositions(); // When the size of the window changes void ViewSizeChanged(int newWidth, int newHeight); // The whole transformation matrix const GLfloat* GetFloatMVP(); // The 'To View Space' transformation matrix const GLfloat* GetFloatToVw(); // The camera position myVec3 GetPosition() {return m_camPosition;} // Simulates a virtual trackball and rotates the 'world' void MouseRotation(int fromX, int fromY, int toX, int toY); double GetTrackballZ(double x, double y, double r); // The used matrices double m_dMode[16]; // The model matrix, rotation in this sample double m_dView[16]; // The view matrix double m_dProj[16]; // The projection matrix double m_dMVP[16]; // The whole transform matrix double m_dToVw[16]; // The 'to View' transform matrix // GLFloat versions. GLdouble is available since OGL 4.0, and we use 3.2 GLfloat m_fMVP[16]; GLfloat m_fToVw[16]; private: bool m_needMVPUpdate; void UpdateMatrices(); // Coordinates in model space myVec3 m_centerOfWorld; double m_radiusOfWorld; myVec3 m_camPosition; myVec3 m_camTarget; myVec3 m_camUp; // Window size in pixels int m_winWidth; int m_winHeight; // Parameters for the projection double m_fov; double m_nearD; double m_farD; }; //----------------------------------------------------------------------------- // General manager class myOGLManager { public: myOGLManager(myOGLErrHandler* extErrHnd = NULL); ~myOGLManager(); // Constants, prototypes and pointers to OGL functions static bool Init(); // Strings describing the current GL connection const GLubyte* GetGLVersion(); const GLubyte* GetGLVendor(); const GLubyte* GetGLRenderer(); // Load data into the GPU void SetShadersAndTriangles(); // Load the texture for the string in the pyramid void SetStringOnPyr(const unsigned char* strImage, int iWidth, int iHeigh); // Load the texture for the immutable string void SetImmutableString(const unsigned char* strImage, int iWidth, int iHeigh); // For window size change void SetViewport(int x, int y, int width, int height); void Render(); // Total rendering // Action events in OpenGL win coordinates (bottom is y=0) void OnMouseButDown(int posX, int posY); void OnMouseRotDragging(int posX, int posY); private: // Members myOGLShaders m_TriangShaders; myOGLShaders m_StringShaders; myOGLShaders m_ImmutStringSha; myLight m_Light; myOGLCamera m_Camera; myOGLTriangles m_Triangles; myOGLString m_StringOnPyr; myOGLImmutString m_ImmString; // For mouse event int m_mousePrevX; int m_mousePrevY; }; #endif //OGLSTUFF_H