wxWidgets/samples/opengl/pyramid/oglstuff.h

341 lines
10 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// 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 <string>
#include <vector>
#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> 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> 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